/// <summary> /// Set the 'args' slot on a python exception object that wraps /// a CLR exception. This is needed for pickling CLR exceptions as /// BaseException_reduce will only check the slots, bypassing the /// __getattr__ implementation, and thus dereferencing a NULL /// pointer. /// </summary> /// <param name="ob">The python object wrapping </param> internal static void SetArgsAndCause(Exception e, IntPtr ob) { IntPtr args; if (!string.IsNullOrEmpty(e.Message)) { args = Runtime.PyTuple_New(1); IntPtr msg = Runtime.PyUnicode_FromString(e.Message); Runtime.PyTuple_SetItem(args, 0, msg); } else { args = Runtime.PyTuple_New(0); } if (Runtime.PyObject_SetAttrString(ob, "args", args) != 0) { throw new PythonException(); } if (e.InnerException != null) { // Note: For an AggregateException, InnerException is only the first of the InnerExceptions. using var cause = CLRObject.GetReference(e.InnerException); Runtime.PyException_SetCause(ob, cause.DangerousMoveToPointer()); } }
/// <summary> /// DelegateObject __new__ implementation. The result of this is a new /// PyObject whose type is DelegateObject and whose ob_data is a handle /// to an actual delegate instance. The method wrapped by the actual /// delegate instance belongs to an object generated to relay the call /// to the Python callable passed in. /// </summary> public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw) { var self = (DelegateObject)GetManagedObject(tp) !; if (!self.type.Valid) { return(Exceptions.RaiseTypeError(self.type.DeletedMessage)); } Type type = self.type.Value; if (Runtime.PyTuple_Size(args) != 1) { return(Exceptions.RaiseTypeError("class takes exactly one argument")); } BorrowedReference method = Runtime.PyTuple_GetItem(args, 0); if (Runtime.PyCallable_Check(method) != 1) { return(Exceptions.RaiseTypeError("argument must be callable")); } Delegate d = PythonEngine.DelegateManager.GetDelegate(type, new PyObject(method)); return(CLRObject.GetReference(d, ClassManager.GetClass(type))); }
/// <summary> /// Set the 'args' slot on a python exception object that wraps /// a CLR exception. This is needed for pickling CLR exceptions as /// BaseException_reduce will only check the slots, bypassing the /// __getattr__ implementation, and thus dereferencing a NULL /// pointer. /// </summary> internal static void SetArgsAndCause(BorrowedReference ob, Exception e) { IntPtr args; if (!string.IsNullOrEmpty(e.Message)) { args = Runtime.PyTuple_New(1); IntPtr msg = Runtime.PyString_FromString(e.Message); Runtime.PyTuple_SetItem(args, 0, msg); } else { args = Runtime.PyTuple_New(0); } using var argsTuple = NewReference.DangerousFromPointer(args); if (Runtime.PyObject_SetAttrString(ob, "args", argsTuple) != 0) { throw PythonException.ThrowLastAsClrException(); } if (e.InnerException != null) { // Note: For an AggregateException, InnerException is only the first of the InnerExceptions. using var cause = CLRObject.GetReference(e.InnerException); Runtime.PyException_SetCause(ob, cause.Steal()); } }
/// <summary> /// Set the 'args' slot on a python exception object that wraps /// a CLR exception. This is needed for pickling CLR exceptions as /// BaseException_reduce will only check the slots, bypassing the /// __getattr__ implementation, and thus dereferencing a NULL /// pointer. /// </summary> internal static bool SetArgsAndCause(BorrowedReference ob, Exception e) { NewReference args; if (!string.IsNullOrEmpty(e.Message)) { args = Runtime.PyTuple_New(1); using var msg = Runtime.PyString_FromString(e.Message); Runtime.PyTuple_SetItem(args.Borrow(), 0, msg.StealOrThrow()); } else { args = Runtime.PyTuple_New(0); } using (args) { if (Runtime.PyObject_SetAttrString(ob, "args", args.Borrow()) != 0) { return(false); } } if (e.InnerException != null) { // Note: For an AggregateException, InnerException is only the first of the InnerExceptions. using var cause = CLRObject.GetReference(e.InnerException); Runtime.PyException_SetCause(ob, cause.Steal()); } return(true); }
internal static NewReference ToPython(object?value, Type type) { if (value is PyObject pyObj) { return(new NewReference(pyObj)); } // Null always converts to None in Python. if (value == null) { return(new NewReference(Runtime.PyNone)); } if (EncodableByUser(type, value)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { return(new NewReference(encoded)); } } if (type.IsInterface) { var ifaceObj = (InterfaceObject)ClassManager.GetClassImpl(type); return(ifaceObj.TryWrapObject(value)); } if (type.IsArray || type.IsEnum) { return(CLRObject.GetReference(value, type)); } // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. var pyderived = value as IPythonDerivedType; if (null != pyderived) { if (!IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } } // ModuleObjects are created in a way that their wrapping them as // a CLRObject fails, the ClassObject has no tpHandle. Return the // pyHandle as is, do not convert. if (value is ModuleObject modobj) { throw new NotImplementedException(); } // hmm - from Python, we almost never care what the declared // type is. we'd rather have the object bound to the actual // implementing class. type = value.GetType(); if (type.IsEnum) { return(CLRObject.GetReference(value, type)); } TypeCode tc = Type.GetTypeCode(type); switch (tc) { case TypeCode.Object: return(CLRObject.GetReference(value, type)); case TypeCode.String: return(Runtime.PyString_FromString((string)value)); case TypeCode.Int32: return(Runtime.PyInt_FromInt32((int)value)); case TypeCode.Boolean: if ((bool)value) { return(new NewReference(Runtime.PyTrue)); } return(new NewReference(Runtime.PyFalse)); case TypeCode.Byte: return(Runtime.PyInt_FromInt32((byte)value)); case TypeCode.Char: return(Runtime.PyUnicode_FromOrdinal((int)((char)value))); case TypeCode.Int16: return(Runtime.PyInt_FromInt32((short)value)); case TypeCode.Int64: return(Runtime.PyLong_FromLongLong((long)value)); case TypeCode.Single: return(Runtime.PyFloat_FromDouble((float)value)); case TypeCode.Double: return(Runtime.PyFloat_FromDouble((double)value)); case TypeCode.SByte: return(Runtime.PyInt_FromInt32((sbyte)value)); case TypeCode.UInt16: return(Runtime.PyInt_FromInt32((ushort)value)); case TypeCode.UInt32: return(Runtime.PyLong_FromUnsignedLongLong((uint)value)); case TypeCode.UInt64: return(Runtime.PyLong_FromUnsignedLongLong((ulong)value)); default: return(CLRObject.GetReference(value, type)); } }