PyDict_GetItemString() private method

private PyDict_GetItemString ( IntPtr pointer, string key ) : IntPtr
pointer IntPtr
key string
return IntPtr
示例#1
0
        static void SetupImportHook()
        {
            // Create the import hook module
            var import_hook_module = Runtime.PyModule_New("clr.loader");

            // Run the python code to create the module's classes.
            var builtins = Runtime.PyEval_GetBuiltins();
            var exec     = Runtime.PyDict_GetItemString(builtins, "exec");

            using var args = NewReference.DangerousFromPointer(Runtime.PyTuple_New(2));

            var codeStr = NewReference.DangerousFromPointer(Runtime.PyString_FromString(LoaderCode));

            Runtime.PyTuple_SetItem(args, 0, codeStr);
            var mod_dict = Runtime.PyModule_GetDict(import_hook_module);

            // reference not stolen due to overload incref'ing for us.
            Runtime.PyTuple_SetItem(args, 1, mod_dict);
            Runtime.PyObject_Call(exec, args, default).Dispose();
            // Set as a sub-module of clr.
            if (Runtime.PyModule_AddObject(ClrModuleReference, "loader", import_hook_module.DangerousGetAddress()) != 0)
            {
                Runtime.XDecref(import_hook_module.DangerousGetAddress());
                throw PythonException.ThrowLastAsClrException();
            }

            // Finally, add the hook to the meta path
            var findercls      = Runtime.PyDict_GetItemString(mod_dict, "DotNetFinder");
            var finderCtorArgs = NewReference.DangerousFromPointer(Runtime.PyTuple_New(0));
            var finder_inst    = Runtime.PyObject_CallObject(findercls, finderCtorArgs);
            var metapath       = Runtime.PySys_GetObject("meta_path");

            Runtime.PyList_Append(metapath, finder_inst);
        }
示例#2
0
        static void SetupImportHook()
        {
            // Create the import hook module
            using var import_hook_module = Runtime.PyModule_New("clr.loader");
            BorrowedReference mod_dict = Runtime.PyModule_GetDict(import_hook_module.BorrowOrThrow());

            Debug.Assert(mod_dict != null);

            // Run the python code to create the module's classes.
            var builtins = Runtime.PyEval_GetBuiltins();
            var exec     = Runtime.PyDict_GetItemString(builtins, "exec");

            using var args = Runtime.PyTuple_New(2);
            PythonException.ThrowIfIsNull(args);
            using var codeStr = Runtime.PyString_FromString(LoaderCode);
            Runtime.PyTuple_SetItem(args.Borrow(), 0, codeStr.StealOrThrow());

            // reference not stolen due to overload incref'ing for us.
            Runtime.PyTuple_SetItem(args.Borrow(), 1, mod_dict);
            Runtime.PyObject_Call(exec, args.Borrow(), default).Dispose();
            // Set as a sub-module of clr.
            if (Runtime.PyModule_AddObject(ClrModuleReference, "loader", import_hook_module.Steal()) != 0)
            {
                throw PythonException.ThrowLastAsClrException();
            }

            // Finally, add the hook to the meta path
            var findercls = Runtime.PyDict_GetItemString(mod_dict, "DotNetFinder");

            using var finderCtorArgs = Runtime.PyTuple_New(0);
            using var finder_inst    = Runtime.PyObject_CallObject(findercls, finderCtorArgs.Borrow());
            var metapath = Runtime.PySys_GetObject("meta_path");

            PythonException.ThrowIfIsNotZero(Runtime.PyList_Append(metapath, finder_inst.BorrowOrThrow()));
        }
示例#3
0
        public static IntPtr CreateObjectType()
        {
            IntPtr globals = Runtime.PyDict_New();

            if (Runtime.PyDict_SetItemString(globals, "__builtins__", Runtime.PyEval_GetBuiltins()) != 0)
            {
                Runtime.XDecref(globals);
                throw new PythonException();
            }
            const string code   = "class A(object): pass";
            var          resRef = Runtime.PyRun_String(code, RunFlagType.File, globals, globals);
            IntPtr       res    = resRef.DangerousGetAddress();

            if (res == IntPtr.Zero)
            {
                try
                {
                    throw new PythonException();
                }
                finally
                {
                    Runtime.XDecref(globals);
                }
            }
            resRef.Dispose();
            IntPtr A = Runtime.PyDict_GetItemString(globals, "A");

            Debug.Assert(A != IntPtr.Zero);
            Runtime.XIncref(A);
            Runtime.XDecref(globals);
            return(A);
        }
示例#4
0
        internal static void SetupExceptionHack()
        {
            ns_exc = ClassManager.GetClass(typeof(Exception)).pyHandle;
            cache  = new Hashtable();

            string code =
                "import exceptions\n" +
                "class Exception(exceptions.Exception):\n" +
                "    _class = None\n" +
                "    _inner = None\n" +
                "\n" +
                "    def __init__(self, *args, **kw):\n" +
                "        inst = self.__class__._class(*args, **kw)\n" +
                "        self.__dict__['_inner'] = inst\n" +
                "        exceptions.Exception.__init__(self, *args, **kw)\n" +
                "\n" +
                "    def __getattr__(self, name, _marker=[]):\n" +
                "        inner = self.__dict__['_inner']\n" +
                "        v = getattr(inner, name, _marker)\n" +
                "        if v is not _marker:\n" +
                "            return v\n" +
                "        v = self.__dict__.get(name, _marker)\n" +
                "        if v is not _marker:\n" +
                "            return v\n" +
                "        raise AttributeError(name)\n" +
                "\n" +
                "    def __setattr__(self, name, value):\n" +
                "        inner = self.__dict__['_inner']\n" +
                "        setattr(inner, name, value)\n" +
                "\n" +
                "    def __str__(self):\n" +
                "        inner = self.__dict__.get('_inner')\n" +
                "        msg = getattr(inner, 'Message', '')\n" +
                "        st = getattr(inner, 'StackTrace', '')\n" +
                "        st = st and '\\n' + st or ''\n" +
                "        return msg + st\n" +
                "\n";

            IntPtr dict = Runtime.PyDict_New();

            IntPtr builtins = Runtime.PyEval_GetBuiltins();

            Runtime.PyDict_SetItemString(dict, "__builtins__", builtins);

            IntPtr namestr = Runtime.PyString_FromString("System");

            Runtime.PyDict_SetItemString(dict, "__name__", namestr);
            Runtime.Decref(namestr);

            Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone);
            Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone);

            IntPtr flag = Runtime.Py_file_input;
            IntPtr done = Runtime.PyRun_String(code, flag, dict, dict);

            os_exc = Runtime.PyDict_GetItemString(dict, "Exception");
            Runtime.PyObject_SetAttrString(os_exc, "_class", ns_exc);
            Runtime.PyErr_Clear();
        }
示例#5
0
        //====================================================================
        // Metatype __new__ implementation. This is called to create a new
        // class / type when a reflected class is subclassed.
        //====================================================================

        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            int len = Runtime.PyTuple_Size(args);

            if (len < 3)
            {
                return(Exceptions.RaiseTypeError("invalid argument list"));
            }

            IntPtr name  = Runtime.PyTuple_GetItem(args, 0);
            IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
            IntPtr dict  = Runtime.PyTuple_GetItem(args, 2);

            // We do not support multiple inheritance, so the bases argument
            // should be a 1-item tuple containing the type we are subtyping.
            // That type must itself have a managed implementation. We check
            // that by making sure its metatype is the CLR metatype.

            if (Runtime.PyTuple_Size(bases) != 1)
            {
                return(Exceptions.RaiseTypeError(
                           "cannot use multiple inheritance with managed classes"
                           ));
            }

            IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0);
            IntPtr mt        = Runtime.PyObject_TYPE(base_type);

            if (!((mt == PyCLRMetaType) || (mt == Runtime.PyTypeType)))
            {
                return(Exceptions.RaiseTypeError("invalid metatype"));
            }

            // Ensure that the reflected type is appropriate for subclassing,
            // disallowing subclassing of delegates, enums and array types.

            ClassBase cb = GetManagedObject(base_type) as ClassBase;

            if (cb != null)
            {
                if (!cb.CanSubclass())
                {
                    return(Exceptions.RaiseTypeError(
                               "delegates, enums and array types cannot be subclassed"
                               ));
                }
            }

            IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");

            if (slots != IntPtr.Zero)
            {
                return(Exceptions.RaiseTypeError(
                           "subclasses of managed classes do not support __slots__"
                           ));
            }

            return(TypeManager.CreateSubType(name, base_type, dict));
        }
示例#6
0
        /// <summary>
        /// Initialization performed on startup of the Python runtime.
        /// </summary>
        internal static void Initialize()
        {
            // Initialize the Python <--> CLR module hook. We replace the
            // built-in Python __import__ with our own. This isn't ideal,
            // but it provides the most "Pythonic" way of dealing with CLR
            // modules (Python doesn't provide a way to emulate packages).
            IntPtr dict = Runtime.PyImport_GetModuleDict();

            IntPtr mod = Runtime.IsPython3
                ? Runtime.PyImport_ImportModule("builtins")
                : Runtime.PyDict_GetItemString(dict, "__builtin__");

            if (mod == IntPtr.Zero)
            {
                throw new PythonException();
            }

            py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
            if (py_import == IntPtr.Zero)
            {
                throw new PythonException();
            }

            hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
            Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);

            if (Runtime.IsPython3)
            {
                // On Python3, PyImport_ImportModule got a new reference, so we need to decrease it.
                Runtime.Py_DecRef(mod);
            }

            root = new CLRModule();

#if PYTHON3
            // create a python module with the same methods as the clr module-like object
            InitializeModuleDef();
            py_clr_module = Runtime.PyModule_Create2(module_def, 3);

            // both dicts are borrowed references
            IntPtr mod_dict = Runtime.PyModule_GetDict(py_clr_module);
            IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject**
            clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr));

            Runtime.PyDict_Update(mod_dict, clr_dict);
#elif PYTHON2
            Runtime.XIncref(root.pyHandle); // we are using the module two times
            py_clr_module = root.pyHandle;  // Alias handle for PY2/PY3
#endif
            Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module);
            Runtime.PyDict_SetItemString(dict, "clr", py_clr_module);
        }
示例#7
0
        /// <summary>
        /// Cleanup resources upon shutdown of the Python runtime.
        /// </summary>
        internal static void Shutdown()
        {
            if (Runtime.Py_IsInitialized() != 0)
            {
                Runtime.XDecref(py_clr_module);
                Runtime.XDecref(root.pyHandle);

                // Re-install the original import function
                IntPtr dict = Runtime.PyImport_GetModuleDict();
                IntPtr mod  = Runtime.IsPython3
                    ? Runtime.PyImport_ImportModule("builtins")
                    : Runtime.PyDict_GetItemString(dict, "__builtin__");
                Runtime.PyObject_SetAttrString(mod, "__import__", py_import);
                Runtime.XDecref(py_import);
            }
        }
示例#8
0
        /// <summary>
        /// Get a <i>New reference</i> to the builtins module.
        /// </summary>
        static IntPtr GetNewRefToBuiltins()
        {
            if (Runtime.IsPython3)
            {
                return(Runtime.PyImport_ImportModule("builtins"));
            }
            else
            {
                // dict is a borrowed ref, no need to decref
                IntPtr dict = Runtime.PyImport_GetModuleDict();

                // GetItemString is a borrowed ref; incref to get a new ref
                IntPtr builtins = Runtime.PyDict_GetItemString(dict, "__builtin__");
                Runtime.XIncref(builtins);
                return(builtins);
            }
        }
示例#9
0
        /// <summary>
        /// Preloads all currently-known names for the module namespace. This
        /// can be called multiple times, to add names from assemblies that
        /// may have been loaded since the last call to the method.
        /// </summary>
        public void LoadNames()
        {
            ManagedType m = null;

            foreach (string name in AssemblyManager.GetNames(_namespace))
            {
                cache.TryGetValue(name, out m);
                if (m != null)
                {
                    continue;
                }
                BorrowedReference attr = Runtime.PyDict_GetItemString(DictRef, name);
                // If __dict__ has already set a custom property, skip it.
                if (!attr.IsNull)
                {
                    continue;
                }
                GetAttribute(name, true);
            }
        }
示例#10
0
        /// <summary>
        /// Preloads all currently-known names for the module namespace. This
        /// can be called multiple times, to add names from assemblies that
        /// may have been loaded since the last call to the method.
        /// </summary>
        public void LoadNames()
        {
            ManagedType m = null;

            foreach (string name in AssemblyManager.GetNames(_namespace))
            {
                cache.TryGetValue(name, out m);
                if (m != null)
                {
                    continue;
                }
                IntPtr attr = Runtime.PyDict_GetItemString(dict, name);
                // If __dict__ has already set a custom property, skip it.
                if (attr != IntPtr.Zero)
                {
                    continue;
                }
                GetAttribute(name, true);
            }
        }
示例#11
0
        //===================================================================
        // Initialization performed on startup of the Python runtime.
        //===================================================================

        internal static void Initialize()
        {
            // Initialize the Python <--> CLR module hook. We replace the
            // built-in Python __import__ with our own. This isn't ideal,
            // but it provides the most "Pythonic" way of dealing with CLR
            // modules (Python doesn't provide a way to emulate packages).

            IntPtr dict = Runtime.PyImport_GetModuleDict();
            IntPtr mod  = Runtime.PyDict_GetItemString(dict, "__builtin__");

            py_import = Runtime.PyObject_GetAttrString(mod, "__import__");

            hook = new MethodWrapper(typeof(ImportHook), "__import__");
            Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
            Runtime.Decref(hook.ptr);

            root = new CLRModule();
            Runtime.Incref(root.pyHandle); // we are using the module two times
            Runtime.PyDict_SetItemString(dict, "CLR", root.pyHandle);
            Runtime.PyDict_SetItemString(dict, "clr", root.pyHandle);
        }
示例#12
0
        //===================================================================
        // Initialization performed on startup of the Python runtime.
        //===================================================================

        internal static void Initialize()
        {
            // Initialize the Python <--> CLR module hook. We replace the
            // built-in Python __import__ with our own. This isn't ideal,
            // but it provides the most "Pythonic" way of dealing with CLR
            // modules (Python doesn't provide a way to emulate packages).
            IntPtr dict = Runtime.PyImport_GetModuleDict();

#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
            IntPtr mod = Runtime.PyImport_ImportModule("builtins");
            py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
#else
            IntPtr mod = Runtime.PyDict_GetItemString(dict, "__builtin__");
            py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
#endif
            hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
            Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
            Runtime.Decref(hook.ptr);

            root = new CLRModule();

#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
            // create a python module with the same methods as the clr module-like object
            module_def    = ModuleDefOffset.AllocModuleDef("clr");
            py_clr_module = Runtime.PyModule_Create2(module_def, 3);

            // both dicts are borrowed references
            IntPtr mod_dict = Runtime.PyModule_GetDict(py_clr_module);
            IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject**
            clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr));

            Runtime.PyDict_Update(mod_dict, clr_dict);
            Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module);
            Runtime.PyDict_SetItemString(dict, "clr", py_clr_module);
#else
            Runtime.Incref(root.pyHandle); // we are using the module two times
            Runtime.PyDict_SetItemString(dict, "CLR", root.pyHandle);
            Runtime.PyDict_SetItemString(dict, "clr", root.pyHandle);
#endif
        }
示例#13
0
        internal static IntPtr UnwrapExceptionClass(IntPtr op)
        {
            // In some cases its necessary to recognize an exception *class*,
            // and obtain the inner (wrapped) exception class. This method
            // returns the inner class if found, or a null pointer.

            IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__");

            if (d == IntPtr.Zero)
            {
                Exceptions.Clear();
                return(IntPtr.Zero);
            }
            IntPtr c = Runtime.PyDict_GetItemString(d, "_class");

            Runtime.Decref(d);
            if (c == IntPtr.Zero)
            {
                Exceptions.Clear();
            }
            return(c);
        }
示例#14
0
        public static IntPtr CreateObjectType()
        {
            using var globals = NewReference.DangerousFromPointer(Runtime.PyDict_New());
            if (Runtime.PyDict_SetItemString(globals, "__builtins__", Runtime.PyEval_GetBuiltins()) != 0)
            {
                globals.Dispose();
                throw new PythonException();
            }
            const string code = "class A(object): pass";

            using var resRef = Runtime.PyRun_String(code, RunFlagType.File, globals, globals);
            if (resRef.IsNull())
            {
                globals.Dispose();
                throw new PythonException();
            }
            resRef.Dispose();
            BorrowedReference A = Runtime.PyDict_GetItemString(globals, "A");

            Debug.Assert(!A.IsNull);
            return(new NewReference(A).DangerousMoveToPointer());
        }
示例#15
0
        /// <summary>
        /// Preloads all currently-known names for the module namespace. This
        /// can be called multiple times, to add names from assemblies that
        /// may have been loaded since the last call to the method.
        /// </summary>
        public void LoadNames()
        {
            ManagedType m = null;

            foreach (string name in AssemblyManager.GetNames(_namespace))
            {
                cache.TryGetValue(name, out m);
                if (m != null)
                {
                    continue;
                }
                BorrowedReference attr = Runtime.PyDict_GetItemString(DictRef, name);
                // If __dict__ has already set a custom property, skip it.
                if (!attr.IsNull)
                {
                    continue;
                }

                if (GetAttribute(name, true) != null)
                {
                    // if it's a valid attribute, add it to __all__
                    var pyname = Runtime.PyString_FromString(name);
                    try
                    {
                        if (Runtime.PyList_Append(new BorrowedReference(__all__), new BorrowedReference(pyname)) != 0)
                        {
                            throw PythonException.ThrowLastAsClrException();
                        }
                    }
                    finally
                    {
                        Runtime.XDecref(pyname);
                    }
                }
            }
        }
示例#16
0
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            int len = Runtime.PyTuple_Size(args);

            if (len < 3)
            {
                return(Exceptions.RaiseTypeError("invalid argument list"));
            }

            IntPtr name  = Runtime.PyTuple_GetItem(args, 0);
            IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
            IntPtr dict  = Runtime.PyTuple_GetItem(args, 2);

            // We do not support multiple inheritance, so the bases argument
            // should be a 1-item tuple containing the type we are subtyping.
            // That type must itself have a managed implementation. We check
            // that by making sure its metatype is the CLR metatype.

            if (Runtime.PyTuple_Size(bases) != 1)
            {
                return(Exceptions.RaiseTypeError(
                           "cannot use multiple inheritance with managed classes"
                           ));
            }

            IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0);
            IntPtr mt        = Runtime.PyObject_TYPE(base_type);

            if (!((mt == PyCLRMetaType) || (mt == Runtime.PyTypeType)))
            {
                return(Exceptions.RaiseTypeError("invalid metatype"));
            }

            // Ensure that the reflected type is appropriate for subclassing,
            // disallowing subclassing of delegates, enums and array types.

            ClassBase cb = GetManagedObject(base_type) as ClassBase;

            if (cb != null)
            {
                if (!cb.CanSubclass())
                {
                    return(Exceptions.RaiseTypeError(
                               "delegates, enums and array types cannot be subclassed"
                               ));
                }
            }

            IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");

            if (slots != IntPtr.Zero)
            {
                return(Exceptions.RaiseTypeError(
                           "subclasses of managed classes do not support __slots__"
                           ));
            }

            // hack for now... fix for 1.0
            //return TypeManager.CreateSubType(args);


            // right way

            IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType,
                                             TypeOffset.tp_new);
            IntPtr type = NativeCall.Call_3(func, tp, args, kw);

            if (type == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            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);

            TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc);

            // Hmm - the standard subtype_traverse, clear look at ob_size to
            // do things, so to allow gc to work correctly we need to move
            // our hidden handle out of ob_size. Then, in theory we can
            // comment this out and still not crash.
            TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse);
            TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear);


            // for now, move up hidden handle...
            IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic());

            Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);

            //DebugUtil.DumpType(base_type);
            //DebugUtil.DumpType(type);

            return(type);
        }
示例#17
0
        //===================================================================
        // The actual import hook that ties Python to the managed world.
        //===================================================================

        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // 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.

            int num_args = Runtime.PyTuple_Size(args);

            if (num_args < 1)
            {
                return(Exceptions.RaiseTypeError(
                           "__import__() takes at least 1 argument (0 given)"
                           ));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if ((py_mod_name == IntPtr.Zero) ||
                (!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.

            IntPtr fromList = IntPtr.Zero;
            bool   fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if ((fromList != IntPtr.Zero) &&
                    (Runtime.PyObject_IsTrue(fromList) == 1))
                {
                    fromlist = true;
                }
            }

            string mod_name = Runtime.GetManagedString(py_mod_name);

            if (mod_name == "CLR")
            {
                Exceptions.deprecation("The CLR module is deprecated. " +
                                       "Please use 'clr'.");
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }

            if (mod_name == "clr")
            {
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }

            string realname = mod_name;

            if (mod_name.StartsWith("CLR."))
            {
                realname = mod_name.Substring(4);
                string msg = String.Format("Importing from the CLR.* namespace " +
                                           "is deprecated. Please import '{0}' directly.", realname);
                Exceptions.deprecation(msg);
            }

            string[] names = realname.Split('.');

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            AssemblyManager.LoadImplicit(realname);
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                return(Runtime.PyObject_Call(py_import, args, kw));
            }

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the exising module.

            IntPtr modules = Runtime.PyImport_GetModuleDict();
            IntPtr module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    Runtime.Incref(module);
                    return(module);
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.Incref(module);
                return(module);
            }
            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();

            for (int i = 0; i < names.Length; i++)
            {
                string      name = names[i];
                ManagedType mt   = tail.GetAttribute(name, true);
                if (!(mt is ModuleObject))
                {
                    string error = String.Format("No module named {0}", name);
                    Exceptions.SetError(Exceptions.ImportError, error);
                    return(IntPtr.Zero);
                }
                if (head == null)
                {
                    head = (ModuleObject)mt;
                }
                tail = (ModuleObject)mt;
                if (CLRModule.preload)
                {
                    tail.LoadNames();
                }
                Runtime.PyDict_SetItemString(modules, tail.moduleName,
                                             tail.pyHandle
                                             );
            }

            ModuleObject mod = fromlist ? tail : head;

            if (fromlist && Runtime.PySequence_Size(fromList) == 1)
            {
                IntPtr fp = Runtime.PySequence_GetItem(fromList, 0);
                if ((!CLRModule.preload) && Runtime.GetManagedString(fp) == "*")
                {
                    mod.LoadNames();
                }
                Runtime.Decref(fp);
            }

            Runtime.Incref(mod.pyHandle);
            return(mod.pyHandle);
        }
示例#18
0
        /// <summary>
        /// Metatype __new__ implementation. This is called to create a new
        /// class / type when a reflected class is subclassed.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            int len = Runtime.PyTuple_Size(args);

            if (len < 3)
            {
                return(Exceptions.RaiseTypeError("invalid argument list"));
            }

            IntPtr name  = Runtime.PyTuple_GetItem(args, 0);
            IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
            IntPtr dict  = Runtime.PyTuple_GetItem(args, 2);

            // We do not support multiple inheritance, so the bases argument
            // should be a 1-item tuple containing the type we are subtyping.
            // That type must itself have a managed implementation. We check
            // that by making sure its metatype is the CLR metatype.

            if (Runtime.PyTuple_Size(bases) != 1)
            {
                return(Exceptions.RaiseTypeError("cannot use multiple inheritance with managed classes"));
            }

            IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0);
            IntPtr mt        = Runtime.PyObject_TYPE(base_type);

            if (!(mt == PyCLRMetaType || mt == Runtime.PyTypeType))
            {
                return(Exceptions.RaiseTypeError("invalid metatype"));
            }

            // Ensure that the reflected type is appropriate for subclassing,
            // disallowing subclassing of delegates, enums and array types.

            var cb = GetManagedObject(base_type) as ClassBase;

            if (cb != null)
            {
                if (!cb.CanSubclass())
                {
                    return(Exceptions.RaiseTypeError("delegates, enums and array types cannot be subclassed"));
                }
            }

            IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");

            if (slots != IntPtr.Zero)
            {
                return(Exceptions.RaiseTypeError("subclasses of managed classes do not support __slots__"));
            }

            // If __assembly__ or __namespace__ are in the class dictionary then create
            // a managed sub type.
            // This creates a new managed type that can be used from .net to call back
            // into python.
            if (IntPtr.Zero != dict)
            {
                Runtime.XIncref(dict);
                using (var clsDict = new PyDict(dict))
                {
                    if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__"))
                    {
                        return(TypeManager.CreateSubType(name, base_type, dict));
                    }
                }
            }

            // otherwise just create a basic type without reflecting back into the managed side.
            IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_new);
            IntPtr type = NativeCall.Call_3(func, tp, args, kw);

            if (type == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            int flags = TypeFlags.Default;

            flags |= TypeFlags.Managed;
            flags |= TypeFlags.HeapType;
            flags |= TypeFlags.BaseType;
            flags |= TypeFlags.Subclass;
            flags |= TypeFlags.HaveGC;
            Util.WriteCLong(type, TypeOffset.tp_flags, flags);

            TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc);

            // Hmm - the standard subtype_traverse, clear look at ob_size to
            // do things, so to allow gc to work correctly we need to move
            // our hidden handle out of ob_size. Then, in theory we can
            // comment this out and still not crash.
            TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse);
            TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear);


            // for now, move up hidden handle...
            IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic());

            Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);

            return(type);
        }
示例#19
0
        /// <summary>
        /// The actual import hook that ties Python to the managed world.
        /// </summary>
        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // 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)"));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if (py_mod_name == IntPtr.Zero ||
                !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.

            IntPtr fromList = IntPtr.Zero;
            var    fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if (fromList != IntPtr.Zero &&
                    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" || mod_name == "CLR")
            {
                if (mod_name == "CLR")
                {
                    Exceptions.deprecation("The CLR module is deprecated. Please use 'clr'.");
                }
                IntPtr clr_module = GetCLRModule(fromList);
                if (clr_module != IntPtr.Zero)
                {
                    IntPtr sys_modules = Runtime.PyImport_GetModuleDict();
                    if (sys_modules != IntPtr.Zero)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module);
            }

            string realname   = mod_name;
            string clr_prefix = null;

            if (mod_name.StartsWith("CLR."))
            {
                clr_prefix = "CLR."; // prepend when adding the module to sys.modules
                realname   = mod_name.Substring(4);
                string msg = $"Importing from the CLR.* namespace is deprecated. Please import '{realname}' directly.";
                Exceptions.deprecation(msg);
            }
            else
            {
                // 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, 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);
                }
                // Otherwise,  just clear the it.
                Exceptions.Clear();
            }

            string[] names = realname.Split('.');

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                var loadExceptions = new List <Exception>();
                if (!AssemblyManager.LoadImplicit(realname, assemblyLoadErrorHandler: loadExceptions.Add))
                {
                    // May be called when a module being imported imports a module.
                    // In particular, I've seen decimal import copy import org.python.core
                    IntPtr importResult = Runtime.PyObject_Call(py_import, args, kw);
                    // TODO: use ModuleNotFoundError in Python 3.6+
                    if (importResult == IntPtr.Zero && loadExceptions.Count > 0 &&
                        Exceptions.ExceptionMatches(Exceptions.ImportError))
                    {
                        loadExceptions.Add(new PythonException());
                        var importError = new PyObject(new BorrowedReference(Exceptions.ImportError));
                        importError.SetAttr("__cause__", new AggregateException(loadExceptions).ToPython());
                        Runtime.PyErr_SetObject(new BorrowedReference(Exceptions.ImportError), importError.Reference);
                    }
                    return(importResult);
                }
            }

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the existing module.
            IntPtr modules = Runtime.PyImport_GetModuleDict();
            IntPtr module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    if (IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(module) as ModuleObject;
                        mod?.LoadNames();
                    }
                    Runtime.XIncref(module);
                    return(module);
                }
                if (clr_prefix != null)
                {
                    return(GetCLRModule(fromList));
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.XIncref(module);
                return(module);
            }
            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))
                {
                    Exceptions.SetError(Exceptions.ImportError, $"No module named {name}");
                    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.pyHandle);

                // If imported from CLR add CLR.<modulename> to sys.modules as well
                if (clr_prefix != null)
                {
                    Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.pyHandle);
                }
            }

            {
                var mod = fromlist ? tail : head;

                if (fromlist && IsLoadAll(fromList))
                {
                    mod.LoadNames();
                }

                Runtime.XIncref(mod.pyHandle);
                return(mod.pyHandle);
            }
        }
示例#20
0
        //===================================================================
        // The actual import hook that ties Python to the managed world.
        //===================================================================

        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // 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.

            int num_args = Runtime.PyTuple_Size(args);

            if (num_args < 1)
            {
                return(Exceptions.RaiseTypeError(
                           "__import__() takes at least 1 argument (0 given)"
                           ));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if ((py_mod_name == IntPtr.Zero) ||
                (!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.

            IntPtr fromList = IntPtr.Zero;
            bool   fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if ((fromList != IntPtr.Zero) &&
                    (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")
            {
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }
            if (mod_name == "CLR")
            {
                Exceptions.deprecation("The CLR module is deprecated. " +
                                       "Please use 'clr'.");
                root.InitializePreload();
                Runtime.Incref(root.pyHandle);
                return(root.pyHandle);
            }
            string realname = mod_name;

            if (mod_name.StartsWith("CLR."))
            {
                realname = mod_name.Substring(4);
                string msg = String.Format("Importing from the CLR.* namespace " +
                                           "is deprecated. Please import '{0}' directly.", realname);
                Exceptions.deprecation(msg);
            }
            else
            {
                // 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, kw);
                if (res != IntPtr.Zero)
                {
                    // There was no error.
                    return(res);
                }
                // There was an error
                if (!Exceptions.ExceptionMatches(Exceptions.ImportError))
                {
                    // and it was NOT an ImportError; bail out here.
                    return(IntPtr.Zero);
                }
                // Otherwise,  just clear the it.
                Exceptions.Clear();
            }

            string[] names = realname.Split('.');

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                bool fromFile = false;
                if (AssemblyManager.LoadImplicit(realname, out fromFile))
                {
                    if (true == fromFile)
                    {
                        string deprWarning = String.Format("\nThe module was found, but not in a referenced namespace.\n" +
                                                           "Implicit loading is deprecated. Please use clr.AddReference(\"{0}\").", realname);
                        Exceptions.deprecation(deprWarning);
                    }
                }
                else
                {
                    // May be called when a module being imported imports a module.
                    // In particular, I've seen decimal import copy import org.python.core
                    return(Runtime.PyObject_Call(py_import, args, kw));
                }
            }

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the exising module.

            IntPtr modules = Runtime.PyImport_GetModuleDict();
            IntPtr module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    Runtime.Incref(module);
                    return(module);
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.Incref(module);
                return(module);
            }
            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();

            for (int i = 0; i < names.Length; i++)
            {
                string      name = names[i];
                ManagedType mt   = tail.GetAttribute(name, true);
                if (!(mt is ModuleObject))
                {
                    string error = String.Format("No module named {0}", name);
                    Exceptions.SetError(Exceptions.ImportError, error);
                    return(IntPtr.Zero);
                }
                if (head == null)
                {
                    head = (ModuleObject)mt;
                }
                tail = (ModuleObject)mt;
                if (CLRModule.preload)
                {
                    tail.LoadNames();
                }
                Runtime.PyDict_SetItemString(modules, tail.moduleName,
                                             tail.pyHandle
                                             );
            }

            ModuleObject mod = fromlist ? tail : head;

            if (fromlist && Runtime.PySequence_Size(fromList) == 1)
            {
                IntPtr fp = Runtime.PySequence_GetItem(fromList, 0);
                if ((!CLRModule.preload) && Runtime.GetManagedString(fp) == "*")
                {
                    mod.LoadNames();
                }
                Runtime.Decref(fp);
            }

            Runtime.Incref(mod.pyHandle);
            return(mod.pyHandle);
        }
示例#21
0
        internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
        {
            var dictRef = new BorrowedReference(py_dict);
            // Utility to create a subtype of a managed type with the ability for the
            // a python subtype able to override the managed implementation
            string name = Runtime.GetManagedString(py_name);

            // the derived class can have class attributes __assembly__ and __module__ which
            // control the name of the assembly and module the new type is created in.
            object assembly     = null;
            object namespaceStr = null;

            using (var assemblyKey = new PyString("__assembly__"))
            {
                var assemblyPtr = Runtime.PyDict_GetItemWithError(dictRef, assemblyKey.Reference);
                if (assemblyPtr.IsNull)
                {
                    if (Exceptions.ErrorOccurred())
                    {
                        return(IntPtr.Zero);
                    }
                }
                else if (!Converter.ToManagedValue(assemblyPtr, typeof(string), out assembly, true))
                {
                    return(Exceptions.RaiseTypeError("Couldn't convert __assembly__ value to string"));
                }

                using (var namespaceKey = new PyString("__namespace__"))
                {
                    var pyNamespace = Runtime.PyDict_GetItemWithError(dictRef, namespaceKey.Reference);
                    if (pyNamespace.IsNull)
                    {
                        if (Exceptions.ErrorOccurred())
                        {
                            return(IntPtr.Zero);
                        }
                    }
                    else if (!Converter.ToManagedValue(pyNamespace, typeof(string), out namespaceStr, true))
                    {
                        return(Exceptions.RaiseTypeError("Couldn't convert __namespace__ value to string"));
                    }
                }
            }

            // create the new managed type subclassing the base managed type
            var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase;

            if (null == baseClass)
            {
                return(Exceptions.RaiseTypeError("invalid base class, expected CLR class type"));
            }

            try
            {
                Type subType = ClassDerivedObject.CreateDerivedType(name,
                                                                    baseClass.type.Value,
                                                                    py_dict,
                                                                    (string)namespaceStr,
                                                                    (string)assembly);

                // create the new ManagedType and python type
                ClassBase subClass = ClassManager.GetClass(subType);
                IntPtr    py_type  = GetTypeHandle(subClass, subType);

                // by default the class dict will have all the C# methods in it, but as this is a
                // derived class we want the python overrides in there instead if they exist.
                var cls_dict = new BorrowedReference(Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict));
                ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, new BorrowedReference(py_dict)));
                Runtime.XIncref(py_type);
                // Update the __classcell__ if it exists
                BorrowedReference cell = Runtime.PyDict_GetItemString(cls_dict, "__classcell__");
                if (!cell.IsNull)
                {
                    ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type));
                    ThrowIfIsNotZero(Runtime.PyDict_DelItemString(cls_dict, "__classcell__"));
                }

                return(py_type);
            }
            catch (Exception e)
            {
                return(Exceptions.RaiseTypeError(e.Message));
            }
        }
示例#22
0
        /// <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);
            }
        }
示例#23
0
        internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
        {
            // Utility to create a subtype of a managed type with the ability for the
            // a python subtype able to override the managed implementation
            string name = Runtime.GetManagedString(py_name);

            // the derived class can have class attributes __assembly__ and __module__ which
            // control the name of the assembly and module the new type is created in.
            object assembly     = null;
            object namespaceStr = null;

            var disposeList = new List <PyObject>();

            try
            {
                var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string)));
                disposeList.Add(assemblyKey);
                if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle))
                {
                    var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle));
                    Runtime.XIncref(pyAssembly.Handle);
                    disposeList.Add(pyAssembly);
                    if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false))
                    {
                        throw new InvalidCastException("Couldn't convert __assembly__ value to string");
                    }
                }

                var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__"));
                disposeList.Add(namespaceKey);
                if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle))
                {
                    var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle));
                    Runtime.XIncref(pyNamespace.Handle);
                    disposeList.Add(pyNamespace);
                    if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false))
                    {
                        throw new InvalidCastException("Couldn't convert __namespace__ value to string");
                    }
                }
            }
            finally
            {
                foreach (PyObject o in disposeList)
                {
                    o.Dispose();
                }
            }

            // create the new managed type subclassing the base managed type
            var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase;

            if (null == baseClass)
            {
                return(Exceptions.RaiseTypeError("invalid base class, expected CLR class type"));
            }

            try
            {
                Type subType = ClassDerivedObject.CreateDerivedType(name,
                                                                    baseClass.type,
                                                                    py_dict,
                                                                    (string)namespaceStr,
                                                                    (string)assembly);

                // create the new ManagedType and python type
                ClassBase subClass = ClassManager.GetClass(subType);
                IntPtr    py_type  = GetTypeHandle(subClass, subType);

                // by default the class dict will have all the C# methods in it, but as this is a
                // derived class we want the python overrides in there instead if they exist.
                IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict);
                Runtime.PyDict_Update(cls_dict, py_dict);
                Runtime.XIncref(py_type);
                // Update the __classcell__ if it exists
                var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__"));
                if (!cell.IsNull)
                {
                    Runtime.PyCell_Set(cell, py_type);
                    Runtime.PyDict_DelItemString(cls_dict, "__classcell__");
                }

                return(py_type);
            }
            catch (Exception e)
            {
                return(Exceptions.RaiseTypeError(e.Message));
            }
        }