//==================================================================== // Exceptions __getattribute__ implementation. // handles Python's args and message attributes //==================================================================== public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } string name = Runtime.GetManagedString(key); if (name == "args") { Exception e = ToException(ob); IntPtr args; if (e.Message != String.Empty) { args = Runtime.PyTuple_New(1); IntPtr msg = Runtime.PyUnicode_FromString(e.Message); Runtime.PyTuple_SetItem(args, 0, msg); } else { args = Runtime.PyTuple_New(0); } return(args); } if (name == "message") { return(ExceptionClassObject.tp_str(ob)); } return(Runtime.PyObject_GenericGetAttr(ob, key)); }
/// <summary> /// We __really__ want to avoid using Python objects or APIs when /// probing for assemblies to load, since our ResolveHandler may be /// called in contexts where we don't have the Python GIL and can't /// even safely try to get it without risking a deadlock ;( /// To work around that, we update a managed copy of sys.path (which /// is the main thing we care about) when UpdatePath is called. The /// import hook calls this whenever it knows its about to use the /// assembly manager, which lets us keep up with changes to sys.path /// in a relatively lightweight and low-overhead way. /// </summary> internal static void UpdatePath() { BorrowedReference list = Runtime.PySys_GetObject("path"); var count = Runtime.PyList_Size(list); var sep = Path.DirectorySeparatorChar; if (count != pypath.Count) { pypath.Clear(); probed.Clear(); for (var i = 0; i < count; i++) { BorrowedReference item = Runtime.PyList_GetItem(list, i); string path = Runtime.GetManagedString(item); if (path != null) { pypath.Add(path == string.Empty ? path : path + sep); } } // for performance we will search for all files in each directory in the path once Parallel.ForEach(pypath.Where(s => { try { lock (filesInPath) { // only search in directory if it exists and we haven't already analyzed it return(Directory.Exists(s) && !filesInPath.ContainsKey(s)); } } catch { // just in case, file operations can throw } return(false); }), path => { var container = new HashSet <string>(); try { foreach (var file in Directory.EnumerateFiles(path) .Where(file => file.EndsWith(".dll") || file.EndsWith(".exe"))) { container.Add(Path.GetFileName(file)); } } catch { // just in case, file operations can throw } lock (filesInPath) { filesInPath[path] = container; } }); } }
//==================================================================== // MethodBinding __getattribute__ implementation. //==================================================================== public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { MethodBinding self = (MethodBinding)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } string name = Runtime.GetManagedString(key); if (name == "__doc__") { IntPtr doc = self.m.GetDocString(); Runtime.Incref(doc); return(doc); } if (name == "__overloads__") { OverloadMapper om = new OverloadMapper(self.m, self.target); Runtime.Incref(om.pyHandle); return(om.pyHandle); } return(Runtime.PyObject_GenericGetAttr(ob, key)); }
/// <summary> /// MethodBinding __getattribute__ implementation. /// </summary> public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (MethodBinding)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } string name = Runtime.GetManagedString(key); switch (name) { case "__doc__": IntPtr doc = self.m.GetDocString(); Runtime.XIncref(doc); return(doc); // FIXME: deprecate __overloads__ soon... case "__overloads__": case "Overloads": var om = new OverloadMapper(self.m, self.target); return(om.pyHandle); default: return(Runtime.PyObject_GenericGetAttr(ob, key)); } }
private static void SetConversionError(IntPtr value, Type target) { IntPtr ob = Runtime.Interop.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); Runtime.XDecref(ob); Exceptions.SetError(Exceptions.TypeError, $"Cannot convert {src} to {target}"); }
/// <summary> /// Repr Method /// </summary> /// <remarks> /// Return a string representation of the object. This method is /// the managed equivalent of the Python expression "repr(object)". /// </remarks> public string Repr() { IntPtr strval = Runtime.PyObject_Repr(obj); string result = Runtime.GetManagedString(strval); Runtime.XDecref(strval); return(result); }
/// <summary> /// ToString Method /// </summary> /// <remarks> /// Return the string representation of the object. This method is /// the managed equivalent of the Python expression "str(object)". /// </remarks> public override string ToString() { IntPtr strval = Runtime.PyObject_Unicode(obj); string result = Runtime.GetManagedString(strval); Runtime.XDecref(strval); return(result); }
//==================================================================== // ModuleObject __getattribute__ implementation. Module attributes // are always either classes or sub-modules representing subordinate // namespaces. CLR modules implement a lazy pattern - the sub-modules // and classes are created when accessed and cached for future use. //==================================================================== public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { ModuleObject self = (ModuleObject)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } IntPtr op = Runtime.PyDict_GetItem(self.dict, key); if (op != IntPtr.Zero) { Runtime.Incref(op); return(op); } string name = Runtime.GetManagedString(key); if (name == "__dict__") { Runtime.Incref(self.dict); return(self.dict); } ManagedType attr = self.GetAttribute(name, true); if (attr == null) { Exceptions.SetError(Exceptions.AttributeError, name); return(IntPtr.Zero); } // XXX - hack required to recognize exception types. These types // may need to be wrapped in old-style class wrappers in versions // of Python where new-style classes cannot be used as exceptions. if (Runtime.wrap_exceptions) { if (attr is ExceptionClassObject) { ExceptionClassObject c = attr as ExceptionClassObject; if (c != null) { IntPtr p = attr.pyHandle; IntPtr r = Exceptions.GetExceptionClassWrapper(p); Runtime.PyDict_SetItemString(self.dict, name, r); Runtime.Incref(r); return(r); } } } Runtime.Incref(attr.pyHandle); return(attr.pyHandle); }
public IncorrectRefCountException(IntPtr ptr) { PyPtr = ptr; IntPtr pyname = Runtime.PyObject_Unicode(PyPtr); string name = Runtime.GetManagedString(pyname); Runtime.XDecref(pyname); _message = $"<{name}> may has a incorrect ref count"; }
public static string GetManagedString(IntPtr op) { string s; if (TryGetInterned(op, out s)) { return(s); } return(Runtime.GetManagedString(op)); }
internal static IntPtr CreateSubType(IntPtr args) { IntPtr py_name = Runtime.PyTuple_GetItem(args, 0); IntPtr bases = Runtime.PyTuple_GetItem(args, 1); IntPtr dict = Runtime.PyTuple_GetItem(args, 2); IntPtr base_ = Runtime.PyTuple_GetItem(bases, 0); string name = Runtime.GetManagedString(py_name); IntPtr type = AllocateTypeObject(name); Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); Runtime.Incref(Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize); Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); IntPtr offset = (IntPtr)ObjectOffset.ob_dict; Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); IntPtr dc = Runtime.PyDict_Copy(dict); Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc); Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.Incref(base_); int flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags); CopySlot(base_, type, TypeOffset.tp_traverse); CopySlot(base_, type, TypeOffset.tp_clear); CopySlot(base_, type, TypeOffset.tp_is_gc); Runtime.PyType_Ready(type); IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); Runtime.PyDict_SetItemString(tp_dict, "__module__", mod); // for now, move up hidden handle... IntPtr gc = Marshal.ReadIntPtr(base_, TypeOffset.magic()); Marshal.WriteIntPtr(type, TypeOffset.magic(), gc); return(type); }
static void SetConversionError(IntPtr value, Type target) { IntPtr ob = Runtime.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); Runtime.Decref(ob); string error = String.Format( "Cannot convert {0} to {1}", src, target ); Exceptions.SetError(Exceptions.TypeError, error); }
private static void SetConversionError(IntPtr value, Type target) { // PyObject_Repr might clear the error Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace); IntPtr ob = Runtime.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); Runtime.XDecref(ob); Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable()); Exceptions.RaiseTypeError($"Cannot convert {src} to {target}"); }
public new static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { var managedKey = Runtime.GetManagedString(key); if ((settableAttributes.Contains(managedKey)) || (ManagedType.GetManagedObject(val)?.GetType() == typeof(ModuleObject))) { var self = (ModuleObject)ManagedType.GetManagedObject(ob); return(Runtime.PyDict_SetItem(self.dict, key, val)); } return(ExtensionType.tp_setattro(ob, key, val)); }
private static bool IsLoadAll(BorrowedReference fromList) { if (CLRModule.preload) { return(false); } if (Runtime.PySequence_Size(fromList) != 1) { return(false); } using var fp = Runtime.PySequence_GetItem(fromList, 0); return(Runtime.GetManagedString(fp) == "*"); }
/// <summary> /// Bind the given Python instance and arguments to a particular method /// overload in <see cref="list"/> and return a structure that contains the converted Python /// instance, converted arguments and the correct method to call. /// If unsuccessful, may set a Python error. /// </summary> /// <param name="inst">The Python target of the method invocation.</param> /// <param name="args">The Python arguments.</param> /// <param name="kw">The Python keyword arguments.</param> /// <param name="info">If not null, only bind to that method.</param> /// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param> /// <returns>A Binding if successful. Otherwise null.</returns> internal Binding?Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw, MethodBase?info, MethodBase[]?methodinfo) { // loop to find match, return invoker w/ or w/o error var kwargDict = new Dictionary <string, PyObject>(); if (kw != null) { nint pynkwargs = Runtime.PyDict_Size(kw); using var keylist = Runtime.PyDict_Keys(kw); using var valueList = Runtime.PyDict_Values(kw); for (int i = 0; i < pynkwargs; ++i) { var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(keylist.Borrow(), i)); BorrowedReference value = Runtime.PyList_GetItem(valueList.Borrow(), i); kwargDict[keyStr !] = new PyObject(value);
private void StoreSearchPaths() { var currentSysPath = GetSysPaths(); _sysPaths = new List <string>(); long itemsCount = currentSysPath.Length(); for (long i = 0; i < itemsCount; i++) { BorrowedReference item = CpyRuntime.PyList_GetItem(currentSysPath.Handle, i); string path = CpyRuntime.GetManagedString(item); _sysPaths.Add(path); } }
public static void Print(string msg, BorrowedReference member) { string result = msg; result += " "; if (member == null) { Console.WriteLine("null arg to print"); } using var ob = Runtime.PyObject_Repr(member); result += Runtime.GetManagedString(ob.BorrowOrThrow()); result += " "; Console.WriteLine(result); }
/// <summary> /// ModuleObject __getattribute__ implementation. Module attributes /// are always either classes or sub-modules representing subordinate /// namespaces. CLR modules implement a lazy pattern - the sub-modules /// and classes are created when accessed and cached for future use. /// </summary> public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (ModuleObject)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { Exceptions.SetError(Exceptions.TypeError, "string expected"); return(IntPtr.Zero); } IntPtr op = Runtime.PyDict_GetItem(self.dict, key); if (op != IntPtr.Zero) { Runtime.XIncref(op); return(op); } string name = Runtime.GetManagedString(key); if (name == "__dict__") { Runtime.XIncref(self.dict); return(self.dict); } ManagedType attr = null; try { attr = self.GetAttribute(name, true); } catch (Exception e) { Exceptions.SetError(e); return(IntPtr.Zero); } if (attr == null) { Exceptions.SetError(Exceptions.AttributeError, name); return(IntPtr.Zero); } Runtime.XIncref(attr.pyHandle); return(attr.pyHandle); }
private static bool IsLoadAll(IntPtr fromList) { if (CLRModule.preload) { return(false); } if (Runtime.PySequence_Size(fromList) != 1) { return(false); } IntPtr fp = Runtime.PySequence_GetItem(fromList, 0); bool res = Runtime.GetManagedString(fp) == "*"; Runtime.XDecref(fp); return(res); }
private static bool IsLoadAll(BorrowedReference fromList) { if (fromList == null) { throw new ArgumentNullException(nameof(fromList)); } if (CLRModule.preload) { return(false); } if (Runtime.PySequence_Size(fromList) != 1) { return(false); } using var fp = Runtime.PySequence_GetItem(fromList, 0); return(Runtime.GetManagedString(fp) == "*"); }
public static void Print(string msg, params IntPtr[] args) { string result = msg; result += " "; foreach (IntPtr t in args) { if (t == IntPtr.Zero) { Console.WriteLine("null arg to print"); } IntPtr ob = Runtime.PyObject_Repr(t); result += Runtime.GetManagedString(ob); Runtime.XDecref(ob); result += " "; } Console.WriteLine(result); }
public static void Print(string msg, params IntPtr[] args) { string result = msg; result += " "; for (int i = 0; i < args.Length; i++) { if (args[i] == IntPtr.Zero) { Console.WriteLine("null arg to print"); } IntPtr ob = Runtime.PyObject_Repr(args[i]); result += Runtime.GetManagedString(ob); Runtime.Decref(ob); result += " "; } Console.WriteLine(result); return; }
/// <summary> /// Descriptor __getattribute__ implementation. /// </summary> public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (MethodObject)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { return(Exceptions.RaiseTypeError("string expected")); } string name = Runtime.GetManagedString(key); if (name == "__doc__") { IntPtr doc = self.GetDocString(); Runtime.XIncref(doc); return(doc); } return(Runtime.PyObject_GenericGetAttr(ob, key)); }
/// <summary> /// We __really__ want to avoid using Python objects or APIs when /// probing for assemblies to load, since our ResolveHandler may be /// called in contexts where we don't have the Python GIL and can't /// even safely try to get it without risking a deadlock ;( /// To work around that, we update a managed copy of sys.path (which /// is the main thing we care about) when UpdatePath is called. The /// import hook calls this whenever it knows its about to use the /// assembly manager, which lets us keep up with changes to sys.path /// in a relatively lightweight and low-overhead way. /// </summary> internal static void UpdatePath() { IntPtr list = Runtime.Interop.PySys_GetObject("path"); int count = Runtime.Interop.PyList_Size(list); if (count != pypath.Count) { pypath.Clear(); probed.Clear(); for (var i = 0; i < count; i++) { IntPtr item = Runtime.Interop.PyList_GetItem(list, i); string path = Runtime.GetManagedString(item); if (path != null) { pypath.Add(path); } } } }
public PythonException() : base() { Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB); Runtime.Incref(_pyType); Runtime.Incref(_pyValue); Runtime.Incref(_pyTB); IntPtr gs = PythonEngine.AcquireLock(); if ((_pyType != IntPtr.Zero) && (_pyValue != IntPtr.Zero)) { string type = new PyObject(_pyType).GetAttr("__name__").ToString(); string message = Runtime.GetManagedString(_pyValue); _message = type + " : " + message; } if (_pyTB != IntPtr.Zero) { PyObject tb_module = PythonEngine.ImportModule("traceback"); _tb = tb_module.InvokeMethod("format_tb", new PyObject(_pyTB)).ToString(); } PythonEngine.ReleaseLock(gs); }
private static void SetConversionError(BorrowedReference value, Type target) { // PyObject_Repr might clear the error Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace); var ob = Runtime.PyObject_Repr(value); string src = "'object has no repr'"; if (ob.IsNull()) { Exceptions.Clear(); } else { src = Runtime.GetManagedString(ob.Borrow()) ?? src; } ob.Dispose(); Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable()); Exceptions.RaiseTypeError($"Cannot convert {src} to {target}"); }
/// <summary> /// Expose the wrapped implementation through attributes in both /// converted/encoded (__implementation__) and raw (__raw_implementation__) form. /// </summary> public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var clrObj = (CLRObject)GetManagedObject(ob); if (!Runtime.PyString_Check(key)) { return(Exceptions.RaiseTypeError("string expected")); } string name = Runtime.GetManagedString(key); if (name == "__implementation__") { return(Converter.ToPython(clrObj.inst)); } else if (name == "__raw_implementation__") { return(CLRObject.GetInstHandle(clrObj.inst)); } return(Runtime.PyObject_GenericGetAttr(ob, key)); }
protected static void AppendArgumentTypes(StringBuilder to, IntPtr args) { long argCount = Runtime.PyTuple_Size(args); to.Append("("); for (long argIndex = 0; argIndex < argCount; argIndex++) { var arg = Runtime.PyTuple_GetItem(args, argIndex); if (arg != IntPtr.Zero) { var type = Runtime.PyObject_Type(arg); if (type != IntPtr.Zero) { try { var description = Runtime.PyObject_Str(type); if (description != IntPtr.Zero) { to.Append(Runtime.GetManagedString(description)); Runtime.XDecref(description); } } finally { Runtime.XDecref(type); } } } if (argIndex + 1 < argCount) { to.Append(", "); } } to.Append(')'); }
/// <summary> /// The actual import hook that ties Python to the managed world. /// </summary> public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw) { var args = new BorrowedReference(argsRaw); // Replacement for the builtin __import__. The original import // hook is saved as this.py_import. This version handles CLR // import and defers to the normal builtin for everything else. var num_args = Runtime.PyTuple_Size(args); if (num_args < 1) { return(Exceptions.RaiseTypeError("__import__() takes at least 1 argument (0 given)")); } BorrowedReference py_mod_name = Runtime.PyTuple_GetItem(args, 0); if (py_mod_name.IsNull || !Runtime.IsStringType(py_mod_name)) { return(Exceptions.RaiseTypeError("string expected")); } // Check whether the import is of the form 'from x import y'. // This determines whether we return the head or tail module. BorrowedReference fromList = default; var fromlist = false; if (num_args >= 4) { fromList = Runtime.PyTuple_GetItem(args, 3); if (fromList != null && Runtime.PyObject_IsTrue(fromList) == 1) { fromlist = true; } } string mod_name = Runtime.GetManagedString(py_mod_name); // Check these BEFORE the built-in import runs; may as well // do the Incref()ed return here, since we've already found // the module. if (mod_name == "clr") { NewReference clr_module = GetCLRModule(fromList); if (!clr_module.IsNull()) { BorrowedReference sys_modules = Runtime.PyImport_GetModuleDict(); if (!sys_modules.IsNull) { Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module); } } return(clr_module.DangerousMoveToPointerOrNull()); } string realname = mod_name; // 2010-08-15: Always seemed smart to let python try first... // This shaves off a few tenths of a second on test_module.py // and works around a quirk where 'sys' is found by the // LoadImplicit() deprecation logic. // Turns out that the AssemblyManager.ResolveHandler() checks to see if any // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very // little sense to me. IntPtr res = Runtime.PyObject_Call(py_import, args.DangerousGetAddress(), kw); if (res != IntPtr.Zero) { // There was no error. if (fromlist && IsLoadAll(fromList)) { var mod = ManagedType.GetManagedObject(res) as ModuleObject; mod?.LoadNames(); } return(res); } // There was an error if (!Exceptions.ExceptionMatches(Exceptions.ImportError)) { // and it was NOT an ImportError; bail out here. return(IntPtr.Zero); } if (mod_name == string.Empty) { // Most likely a missing relative import. // For example site-packages\bs4\builder\__init__.py uses it to check if a package exists: // from . import _html5lib // We don't support them anyway return(IntPtr.Zero); } // Save the exception var originalException = new PythonException(); // Otherwise, just clear the it. Exceptions.Clear(); string[] names = realname.Split('.'); // See if sys.modules for this interpreter already has the // requested module. If so, just return the existing module. BorrowedReference modules = Runtime.PyImport_GetModuleDict(); BorrowedReference module = Runtime.PyDict_GetItem(modules, py_mod_name); if (module != null) { if (fromlist) { if (IsLoadAll(fromList)) { var mod = ManagedType.GetManagedObject(module) as ModuleObject; mod?.LoadNames(); } return(new NewReference(module).DangerousMoveToPointer()); } module = Runtime.PyDict_GetItemString(modules, names[0]); return(new NewReference(module, canBeNull: true).DangerousMoveToPointer()); } Exceptions.Clear(); // Traverse the qualified module name to get the named module // and place references in sys.modules as we go. Note that if // we are running in interactive mode we pre-load the names in // each module, which is often useful for introspection. If we // are not interactive, we stick to just-in-time creation of // objects at lookup time, which is much more efficient. // NEW: The clr got a new module variable preload. You can // enable preloading in a non-interactive python processing by // setting clr.preload = True ModuleObject head = mod_name == realname ? null : root; ModuleObject tail = root; root.InitializePreload(); foreach (string name in names) { ManagedType mt = tail.GetAttribute(name, true); if (!(mt is ModuleObject)) { originalException.Restore(); return(IntPtr.Zero); } if (head == null) { head = (ModuleObject)mt; } tail = (ModuleObject)mt; if (CLRModule.preload) { tail.LoadNames(); } // Add the module to sys.modules Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.ObjectReference); } { var mod = fromlist ? tail : head; if (fromlist && IsLoadAll(fromList)) { mod.LoadNames(); } Runtime.XIncref(mod.pyHandle); return(mod.pyHandle); } }