Example #1
0
        public ExtensionType()
        {
            // Create a new PyObject whose type is a generated type that is
            // implemented by the particular concrete ExtensionType subclass.
            // The Python instance object is related to an instance of a
            // particular concrete subclass with a hidden CLR gchandle.

            BorrowedReference tp = TypeManager.GetTypeReference(GetType());

            //int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt);
            //if (rc > 1050)
            //{
            //    DebugUtil.Print("tp is: ", tp);
            //    DebugUtil.DumpType(tp);
            //}

            NewReference py = Runtime.PyType_GenericAlloc(tp, 0);

            // Borrowed reference. Valid as long as pyHandle is valid.
            tpHandle = tp.DangerousGetAddress();
            pyHandle = py.DangerousMoveToPointer();

#if DEBUG
            GetGCHandle(ObjectReference, TypeReference, out var existing);
            System.Diagnostics.Debug.Assert(existing == IntPtr.Zero);
#endif
            SetupGc();
        }
Example #2
0
        /// <summary>
        /// Set the 'args' slot on a python exception object that wraps
        /// a CLR exception. This is needed for pickling CLR exceptions as
        /// BaseException_reduce will only check the slots, bypassing the
        /// __getattr__ implementation, and thus dereferencing a NULL
        /// pointer.
        /// </summary>
        internal static void SetArgsAndCause(BorrowedReference ob, Exception e)
        {
            IntPtr args;

            if (!string.IsNullOrEmpty(e.Message))
            {
                args = Runtime.PyTuple_New(1);
                IntPtr msg = Runtime.PyString_FromString(e.Message);
                Runtime.PyTuple_SetItem(args, 0, msg);
            }
            else
            {
                args = Runtime.PyTuple_New(0);
            }

            using var argsTuple = NewReference.DangerousFromPointer(args);

            if (Runtime.PyObject_SetAttrString(ob, "args", argsTuple) != 0)
            {
                throw PythonException.ThrowLastAsClrException();
            }

            if (e.InnerException != null)
            {
                // Note: For an AggregateException, InnerException is only the first of the InnerExceptions.
                using var cause = CLRObject.GetReference(e.InnerException);
                Runtime.PyException_SetCause(ob, cause.Steal());
            }
        }
Example #3
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);
        }
Example #4
0
        /// <summary>
        /// Given a module or package name, import the
        /// module and return the resulting module object as a <see cref="PyModule"/>.
        /// </summary>
        /// <param name="name">Fully-qualified module or package name</param>
        public static PyModule Import(string name)
        {
            NewReference op = Runtime.PyImport_ImportModule(name);

            PythonException.ThrowIfIsNull(op);
            return(new PyModule(ref op));
        }
Example #5
0
        /// <summary>
        /// Reloads the module, and returns the updated object
        /// </summary>
        public PyModule Reload()
        {
            NewReference op = Runtime.PyImport_ReloadModule(this.Reference);

            PythonException.ThrowIfIsNull(op);
            return(new PyModule(ref op));
        }
Example #6
0
        public virtual NewReference Alloc()
        {
            // Create a new PyObject whose type is a generated type that is
            // implemented by the particular concrete ExtensionType subclass.
            // The Python instance object is related to an instance of a
            // particular concrete subclass with a hidden CLR gchandle.

            BorrowedReference tp = TypeManager.GetTypeReference(GetType());

            //int rc = (int)Util.ReadIntPtr(tp, TypeOffset.ob_refcnt);
            //if (rc > 1050)
            //{
            //    DebugUtil.Print("tp is: ", tp);
            //    DebugUtil.DumpType(tp);
            //}

            NewReference py = Runtime.PyType_GenericAlloc(tp, 0);

#if DEBUG
            GetGCHandle(py.BorrowOrThrow(), tp, out var existing);
            System.Diagnostics.Debug.Assert(existing == IntPtr.Zero);
#endif
            SetupGc(py.Borrow(), tp);

            return(py);
        }
Example #7
0
 private void Exec(string code, BorrowedReference _globals, BorrowedReference _locals)
 {
     using NewReference reference = Runtime.PyRun_String(
               code, RunFlagType.File, _globals, _locals
               );
     PythonException.ThrowIfIsNull(reference);
 }
Example #8
0
 private static IntPtr FromString(string value)
 {
     using (var s = new PyString(value))
     {
         NewReference val = Runtime.PyFloat_FromString(s.Reference);
         PythonException.ThrowIfIsNull(val);
         return(val.DangerousMoveToPointerOrNull());
     }
 }
Example #9
0
        public static PyModule FromString(string name, string code)
        {
            using NewReference c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File);
            PythonException.ThrowIfIsNull(c);
            NewReference m = Runtime.PyImport_ExecCodeModule(name, c);

            PythonException.ThrowIfIsNull(m);
            return(new PyModule(ref m));
        }
Example #10
0
        private void Exec(string code, IntPtr _globals, IntPtr _locals)
        {
            NewReference reference = Runtime.PyRun_String(
                code, RunFlagType.File, _globals, _locals
                );

            PythonException.ThrowIfIsNull(reference);
            reference.Dispose();
        }
Example #11
0
        /// <summary>
        /// Creates <see cref="CLRObject"/> proxy for the given object,
        /// and returns a <see cref="NewReference"/> to it.
        /// </summary>
        internal static NewReference MakeNewReference(object obj)
        {
            if (obj is null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            // TODO: CLRObject currently does not have Dispose or finalizer which might change in the future
            return(NewReference.DangerousFromPointer(GetInstHandle(obj)));
        }
Example #12
0
        private void Exec(string code, IntPtr _globals, IntPtr _locals)
        {
            var          flag      = (IntPtr)Runtime.Py_file_input;
            NewReference reference = Runtime.PyRun_String(
                code, flag, _globals, _locals
                );

            PythonException.ThrowIfIsNull(reference);
            reference.Dispose();
        }
Example #13
0
        public static void Save()
        {
            if (!PySys_GetObject("dummy_gc").IsNull)
            {
                throw new Exception("Runtime State set already");
            }

            NewReference objs = default;

            if (ShouldRestoreObjects)
            {
                objs = PySet_New(default);
Example #14
0
        /// <summary>
        /// Eval method
        /// </summary>
        /// <remarks>
        /// Evaluate a Python expression and return the result as a PyObject
        /// or null if an exception is raised.
        /// </remarks>
        public PyObject Eval(string code, PyDict locals = null)
        {
            Check();
            IntPtr _locals = locals == null ? variables : locals.obj;

            NewReference reference = Runtime.PyRun_String(
                code, RunFlagType.Eval, variables, _locals
                );

            PythonException.ThrowIfIsNull(reference);
            return(reference.MoveToPyObject());
        }
Example #15
0
        /// <summary>
        /// Eval method
        /// </summary>
        /// <remarks>
        /// Evaluate a Python expression and return the result as a PyObject
        /// or null if an exception is raised.
        /// </remarks>
        public PyObject Eval(string code, PyDict locals = null)
        {
            Check();
            BorrowedReference _locals = locals == null ? VarsRef : locals.Reference;

            NewReference reference = Runtime.PyRun_String(
                code, RunFlagType.Eval, VarsRef, _locals
                );

            PythonException.ThrowIfIsNull(reference);
            return(reference.MoveToPyObject());
        }
Example #16
0
        /// <summary>
        /// Return the clr python module (new reference)
        /// </summary>
        public static unsafe NewReference GetCLRModule(BorrowedReference fromList = default)
        {
            root.InitializePreload();

            // update the module dictionary with the contents of the root dictionary
            root.LoadNames();
            BorrowedReference py_mod_dict = Runtime.PyModule_GetDict(ClrModuleReference);

            using (var clr_dict = Runtime.PyObject_GenericGetDict(root.ObjectReference))
            {
                Runtime.PyDict_Update(py_mod_dict, clr_dict);
            }

            // find any items from the from list and get them from the root if they're not
            // already in the module dictionary
            if (fromList != null)
            {
                if (Runtime.PyTuple_Check(fromList))
                {
                    using var mod_dict = new PyDict(py_mod_dict);
                    using var from     = new PyTuple(fromList);
                    foreach (PyObject item in from)
                    {
                        if (mod_dict.HasKey(item))
                        {
                            continue;
                        }

                        var s = item.AsManagedObject(typeof(string)) as string;
                        if (s == null)
                        {
                            continue;
                        }

                        ManagedType attr = root.GetAttribute(s, true);
                        if (attr == null)
                        {
                            continue;
                        }

                        Runtime.XIncref(attr.pyHandle);
                        using (var obj = new PyObject(attr.pyHandle))
                        {
                            mod_dict.SetItem(s, obj);
                        }
                    }
                }
            }
            Runtime.XIncref(py_clr_module);
            return(NewReference.DangerousFromPointer(py_clr_module));
        }
Example #17
0
        internal static Exception?FetchCurrentOrNull(out ExceptionDispatchInfo?dispatchInfo)
        {
            dispatchInfo = null;

            // prevent potential interop errors in this method
            // from crashing process with undebuggable StackOverflowException
            RuntimeHelpers.EnsureSufficientExecutionStack();

            using var _ = new Py.GILState();
            Runtime.PyErr_Fetch(out var type, out var value, out var traceback);
            if (type.IsNull())
            {
                Debug.Assert(value.IsNull());
                Debug.Assert(traceback.IsNull());
                return(null);
            }

            try
            {
                if (TryDecodePyErr(type.Borrow(), value.BorrowNullable(), traceback.BorrowNullable()) is { } pyErr)
                {
                    type.Dispose();
                    value.Dispose();
                    traceback.Dispose();
                    return(pyErr);
                }
            }
            catch
            {
                type.Dispose();
                value.Dispose();
                traceback.Dispose();
                throw;
            }

            var normalizedValue = new NewReference(value.Borrow());

            Runtime.PyErr_NormalizeException(type: ref type, val: ref normalizedValue, tb: ref traceback);

            try
            {
                return(FromPyErr(typeRef: type.Borrow(), valRef: value.Borrow(), nValRef: normalizedValue.Borrow(), tbRef: traceback.BorrowNullable(), out dispatchInfo));
            }
            finally
            {
                type.Dispose();
                value.Dispose();
                traceback.Dispose();
            }
        }
Example #18
0
        /// <summary>
        /// Helper to get docstring from reflected constructor info.
        /// </summary>
        internal NewReference GetDocString()
        {
            MethodBase[] methods = binder.GetMethods();
            var          str     = "";

            foreach (MethodBase t in methods)
            {
                if (str.Length > 0)
                {
                    str += Environment.NewLine;
                }
                str += t.ToString();
            }
            return(NewReference.DangerousFromPointer(Runtime.PyString_FromString(str)));
        }
Example #19
0
        /// <summary>
        /// Internal RunString Method.
        /// </summary>
        /// <remarks>
        /// Run a string containing Python code. Returns the result of
        /// executing the code string as a PyObject instance, or null if
        /// an exception was raised.
        /// </remarks>
        internal static PyObject RunString(string code, IntPtr?globals, IntPtr?locals, RunFlagType flag)
        {
            var borrowedGlobals = true;

            if (globals == null)
            {
                globals = Runtime.PyEval_GetGlobals();
                if (globals == IntPtr.Zero)
                {
                    globals = Runtime.PyDict_New();
                    Runtime.PyDict_SetItemString(
                        globals.Value, "__builtins__",
                        Runtime.PyEval_GetBuiltins()
                        );
                    borrowedGlobals = false;
                }
            }

            if (locals == null)
            {
                locals = globals;
            }

            try
            {
                NewReference result = Runtime.PyRun_String(
                    code, (IntPtr)flag, globals.Value, locals.Value
                    );

                try
                {
                    Runtime.CheckExceptionOccurred();

                    return(result.MoveToPyObject());
                }
                finally
                {
                    result.Dispose();
                }
            }
            finally
            {
                if (!borrowedGlobals)
                {
                    Runtime.XDecref(globals.Value);
                }
            }
        }
Example #20
0
        /// <summary>
        /// The following CreateType implementations do the necessary work to
        /// create Python types to represent managed extension types, reflected
        /// types, subclasses of reflected types and the managed metatype. The
        /// dance is slightly different for each kind of type due to different
        /// behavior needed and the desire to have the existing Python runtime
        /// do as much of the allocation and initialization work as possible.
        /// </summary>
        internal static unsafe IntPtr CreateType(Type impl)
        {
            IntPtr type  = AllocateTypeObject(impl.Name, metatype: Runtime.PyCLRMetaType);
            IntPtr base_ = impl == typeof(CLRModule)
                ? Runtime.PyModuleType
                : Runtime.PyBaseObjectType;

            int newFieldOffset = InheritOrAllocateStandardFields(type, base_);

            int tp_clr_inst_offset = newFieldOffset;

            newFieldOffset += IntPtr.Size;

            int ob_size = newFieldOffset;

            // Set tp_basicsize to the size of our managed instance objects.
            Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size);
            Marshal.WriteInt32(type, ManagedType.Offsets.tp_clr_inst_offset, tp_clr_inst_offset);
            Marshal.WriteIntPtr(type, TypeOffset.tp_new, (IntPtr)Runtime.Delegates.PyType_GenericNew);

            SlotsHolder slotsHolder = CreateSolotsHolder(type);

            InitializeSlots(type, impl, slotsHolder);

            var flags = TypeFlags.Default | TypeFlags.HasClrInstance |
                        TypeFlags.HeapType | TypeFlags.HaveGC;

            Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags);

            if (Runtime.PyType_Ready(type) != 0)
            {
                throw new PythonException();
            }

            var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict));
            var mod  = NewReference.DangerousFromPointer(Runtime.PyString_FromString("CLR"));

            Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod);
            mod.Dispose();

            InitMethods(type, impl);

            // The type has been modified after PyType_Ready has been called
            // Refresh the type
            Runtime.PyType_Modified(type);
            return(type);
        }
Example #21
0
        public bool MoveNext()
        {
            NewReference next = Runtime.PyIter_Next(Reference);

            if (next.IsNull())
            {
                if (Exceptions.ErrorOccurred())
                {
                    throw new PythonException();
                }

                // stop holding the previous object, if there was one
                _current = null;
                return(false);
            }

            _current = next.MoveToPyObject();
            return(true);
        }
Example #22
0
        /// <summary>
        /// Eval method
        /// </summary>
        /// <remarks>
        /// Evaluate a Python expression and return the result as a PyObject
        /// or null if an exception is raised.
        /// </remarks>
        public PyObject Eval(string code, PyDict locals = null)
        {
            Check();
            IntPtr _locals = locals == null ? variables : locals.obj;
            var    flag    = (IntPtr)Runtime.Py_eval_input;

            NewReference reference = Runtime.PyRun_String(
                code, flag, variables, _locals
                );

            try
            {
                Runtime.CheckExceptionOccurred();
                return(reference.MoveToPyObject());
            }
            finally
            {
                reference.Dispose();
            }
        }
Example #23
0
        private void Exec(string code, IntPtr _globals, IntPtr _locals)
        {
            var          flag      = (IntPtr)Runtime.Py_file_input;
            NewReference reference = Runtime.PyRun_String(
                code, flag, _globals, _locals
                );

            try
            {
                Runtime.CheckExceptionOccurred();
                if (!reference.IsNone())
                {
                    throw new PythonException();
                }
            }
            finally
            {
                reference.Dispose();
            }
        }
Example #24
0
        public new static void tp_dealloc(NewReference ob)
        {
            var self = (CLRObject?)GetManagedObject(ob.Borrow());

            // don't let the python GC destroy this object
            Runtime.PyObject_GC_UnTrack(ob.Borrow());

            // self may be null after Shutdown begun
            if (self is not null)
            {
                // The python should now have a ref count of 0, but we don't actually want to
                // deallocate the object until the C# object that references it is destroyed.
                // So we don't call PyObject_GC_Del here and instead we set the python
                // reference to a weak reference so that the C# object can be collected.
                GCHandle oldHandle = GetGCHandle(ob.Borrow());
                GCHandle gc        = GCHandle.Alloc(self, GCHandleType.Weak);
                SetGCHandle(ob.Borrow(), gc);
                oldHandle.Free();
            }
        }
Example #25
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// Create a scope based on a Python Module.
        /// </remarks>
        internal PyScope(ref NewReference ptr, PyScopeManager manager)
        {
            if (!Runtime.PyType_IsSubtype(Runtime.PyObject_TYPE(ptr), Runtime.PyModuleType))
            {
                throw new PyScopeException("object is not a module");
            }
            Manager = manager ?? PyScopeManager.Global;
            obj     = ptr.MoveToPyObject();
            //Refcount of the variables not increase
            variables = Runtime.PyModule_GetDict(Reference).DangerousGetAddress();
            PythonException.ThrowIfIsNull(variables);

            int res = Runtime.PyDict_SetItem(
                VarsRef, PyIdentifier.__builtins__,
                Runtime.PyEval_GetBuiltins()
                );

            PythonException.ThrowIfIsNotZero(res);
            this.Name = this.Get <string>("__name__");
        }
Example #26
0
        public ModuleObject(string name)
        {
            if (name == string.Empty)
            {
                throw new ArgumentException("Name must not be empty!");
            }
            moduleName = name;
            cache      = new Dictionary <string, ManagedType>();
            _namespace = name;

            // Use the filename from any of the assemblies just so there's something for
            // anything that expects __file__ to be set.
            var filename  = "unknown";
            var docstring = "Namespace containing types from the following assemblies:\n\n";

            foreach (Assembly a in AssemblyManager.GetAssemblies(name))
            {
                if (!a.IsDynamic && a.Location != null)
                {
                    filename = a.Location;
                }
                docstring += "- " + a.FullName + "\n";
            }

            var dictRef = Runtime.PyObject_GenericGetDict(ObjectReference);

            PythonException.ThrowIfIsNull(dictRef);
            dict = dictRef.DangerousMoveToPointer();

            using var pyname      = NewReference.DangerousFromPointer(Runtime.PyString_FromString(moduleName));
            using var pyfilename  = NewReference.DangerousFromPointer(Runtime.PyString_FromString(filename));
            using var pydocstring = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docstring));
            BorrowedReference pycls = TypeManager.GetTypeReference(GetType());

            Runtime.PyDict_SetItem(DictRef, PyIdentifier.__name__, pyname);
            Runtime.PyDict_SetItem(DictRef, PyIdentifier.__file__, pyfilename);
            Runtime.PyDict_SetItem(DictRef, PyIdentifier.__doc__, pydocstring);
            Runtime.PyDict_SetItem(DictRef, PyIdentifier.__class__, pycls);

            InitializeModuleMembers();
        }
Example #27
0
        private static PyModule Create(string name, string filename = null)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            NewReference op = Runtime.PyModule_New(name);

            PythonException.ThrowIfIsNull(op);

            if (filename != null)
            {
                BorrowedReference globals = Runtime.PyModule_GetDict(op);
                PythonException.ThrowIfIsNull(globals);
                int rc = Runtime.PyDict_SetItemString(globals, "__file__", filename.ToPython().Reference);
                PythonException.ThrowIfIsNotZero(rc);
            }

            return(new PyModule(ref op));
        }
Example #28
0
        /// <summary>
        /// The following CreateType implementations do the necessary work to
        /// create Python types to represent managed extension types, reflected
        /// types, subclasses of reflected types and the managed metatype. The
        /// dance is slightly different for each kind of type due to different
        /// behavior needed and the desire to have the existing Python runtime
        /// do as much of the allocation and initialization work as possible.
        /// </summary>
        internal static IntPtr CreateType(Type impl)
        {
            IntPtr type    = AllocateTypeObject(impl.Name, metatype: Runtime.PyTypeType);
            int    ob_size = ObjectOffset.Size(type);

            // Set tp_basicsize to the size of our managed instance objects.
            Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size);

            var offset = (IntPtr)ObjectOffset.TypeDictOffset(type);

            Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);

            SlotsHolder slotsHolder = CreateSolotsHolder(type);

            InitializeSlots(type, impl, slotsHolder);

            var flags = TypeFlags.Default | TypeFlags.Managed |
                        TypeFlags.HeapType | TypeFlags.HaveGC;

            Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags);

            if (Runtime.PyType_Ready(type) != 0)
            {
                throw new PythonException();
            }

            var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict));
            var mod  = NewReference.DangerousFromPointer(Runtime.PyString_FromString("CLR"));

            Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod);
            mod.Dispose();

            InitMethods(type, impl);

            // The type has been modified after PyType_Ready has been called
            // Refresh the type
            Runtime.PyType_Modified(type);
            return(type);
        }
Example #29
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());
        }
Example #30
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);
            }
        }