GetManagedString() static private method

static private GetManagedString ( IntPtr op ) : string
op System.IntPtr
return string
Beispiel #1
0
        //====================================================================
        // Exceptions __getattribute__ implementation.
        // handles Python's args and message attributes
        //====================================================================

        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            if (!Runtime.PyString_Check(key))
            {
                Exceptions.SetError(Exceptions.TypeError, "string expected");
                return(IntPtr.Zero);
            }

            string name = Runtime.GetManagedString(key);

            if (name == "args")
            {
                Exception e = ToException(ob);
                IntPtr    args;
                if (e.Message != String.Empty)
                {
                    args = Runtime.PyTuple_New(1);
                    IntPtr msg = Runtime.PyUnicode_FromString(e.Message);
                    Runtime.PyTuple_SetItem(args, 0, msg);
                }
                else
                {
                    args = Runtime.PyTuple_New(0);
                }
                return(args);
            }

            if (name == "message")
            {
                return(ExceptionClassObject.tp_str(ob));
            }

            return(Runtime.PyObject_GenericGetAttr(ob, key));
        }
Beispiel #2
0
        /// <summary>
        /// We __really__ want to avoid using Python objects or APIs when
        /// probing for assemblies to load, since our ResolveHandler may be
        /// called in contexts where we don't have the Python GIL and can't
        /// even safely try to get it without risking a deadlock ;(
        /// To work around that, we update a managed copy of sys.path (which
        /// is the main thing we care about) when UpdatePath is called. The
        /// import hook calls this whenever it knows its about to use the
        /// assembly manager, which lets us keep up with changes to sys.path
        /// in a relatively lightweight and low-overhead way.
        /// </summary>
        internal static void UpdatePath()
        {
            BorrowedReference list = Runtime.PySys_GetObject("path");
            var count = Runtime.PyList_Size(list);
            var sep   = Path.DirectorySeparatorChar;

            if (count != pypath.Count)
            {
                pypath.Clear();
                probed.Clear();

                for (var i = 0; i < count; i++)
                {
                    BorrowedReference item = Runtime.PyList_GetItem(list, i);
                    string            path = Runtime.GetManagedString(item);
                    if (path != null)
                    {
                        pypath.Add(path == string.Empty ? path : path + sep);
                    }
                }

                // for performance we will search for all files in each directory in the path once
                Parallel.ForEach(pypath.Where(s =>
                {
                    try
                    {
                        lock (filesInPath)
                        {
                            // only search in directory if it exists and we haven't already analyzed it
                            return(Directory.Exists(s) && !filesInPath.ContainsKey(s));
                        }
                    }
                    catch
                    {
                        // just in case, file operations can throw
                    }
                    return(false);
                }), path =>
                {
                    var container = new HashSet <string>();
                    try
                    {
                        foreach (var file in Directory.EnumerateFiles(path)
                                 .Where(file => file.EndsWith(".dll") || file.EndsWith(".exe")))
                        {
                            container.Add(Path.GetFileName(file));
                        }
                    }
                    catch
                    {
                        // just in case, file operations can throw
                    }

                    lock (filesInPath)
                    {
                        filesInPath[path] = container;
                    }
                });
            }
        }
Beispiel #3
0
        //====================================================================
        // MethodBinding __getattribute__ implementation.
        //====================================================================

        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            MethodBinding self = (MethodBinding)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                Exceptions.SetError(Exceptions.TypeError, "string expected");
                return(IntPtr.Zero);
            }

            string name = Runtime.GetManagedString(key);

            if (name == "__doc__")
            {
                IntPtr doc = self.m.GetDocString();
                Runtime.Incref(doc);
                return(doc);
            }

            if (name == "__overloads__")
            {
                OverloadMapper om = new OverloadMapper(self.m, self.target);
                Runtime.Incref(om.pyHandle);
                return(om.pyHandle);
            }

            return(Runtime.PyObject_GenericGetAttr(ob, key));
        }
Beispiel #4
0
        /// <summary>
        /// MethodBinding __getattribute__ implementation.
        /// </summary>
        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            var self = (MethodBinding)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                Exceptions.SetError(Exceptions.TypeError, "string expected");
                return(IntPtr.Zero);
            }

            string name = Runtime.GetManagedString(key);

            switch (name)
            {
            case "__doc__":
                IntPtr doc = self.m.GetDocString();
                Runtime.XIncref(doc);
                return(doc);

            // FIXME: deprecate __overloads__ soon...
            case "__overloads__":
            case "Overloads":
                var om = new OverloadMapper(self.m, self.target);
                return(om.pyHandle);

            default:
                return(Runtime.PyObject_GenericGetAttr(ob, key));
            }
        }
Beispiel #5
0
        private static void SetConversionError(IntPtr value, Type target)
        {
            IntPtr ob  = Runtime.Interop.PyObject_Repr(value);
            string src = Runtime.GetManagedString(ob);

            Runtime.XDecref(ob);
            Exceptions.SetError(Exceptions.TypeError, $"Cannot convert {src} to {target}");
        }
Beispiel #6
0
        /// <summary>
        /// Repr Method
        /// </summary>
        /// <remarks>
        /// Return a string representation of the object. This method is
        /// the managed equivalent of the Python expression "repr(object)".
        /// </remarks>
        public string Repr()
        {
            IntPtr strval = Runtime.PyObject_Repr(obj);
            string result = Runtime.GetManagedString(strval);

            Runtime.XDecref(strval);
            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// ToString Method
        /// </summary>
        /// <remarks>
        /// Return the string representation of the object. This method is
        /// the managed equivalent of the Python expression "str(object)".
        /// </remarks>
        public override string ToString()
        {
            IntPtr strval = Runtime.PyObject_Unicode(obj);
            string result = Runtime.GetManagedString(strval);

            Runtime.XDecref(strval);
            return(result);
        }
Beispiel #8
0
        //====================================================================
        // ModuleObject __getattribute__ implementation. Module attributes
        // are always either classes or sub-modules representing subordinate
        // namespaces. CLR modules implement a lazy pattern - the sub-modules
        // and classes are created when accessed and cached for future use.
        //====================================================================

        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            ModuleObject self = (ModuleObject)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                Exceptions.SetError(Exceptions.TypeError, "string expected");
                return(IntPtr.Zero);
            }

            IntPtr op = Runtime.PyDict_GetItem(self.dict, key);

            if (op != IntPtr.Zero)
            {
                Runtime.Incref(op);
                return(op);
            }

            string name = Runtime.GetManagedString(key);

            if (name == "__dict__")
            {
                Runtime.Incref(self.dict);
                return(self.dict);
            }

            ManagedType attr = self.GetAttribute(name, true);

            if (attr == null)
            {
                Exceptions.SetError(Exceptions.AttributeError, name);
                return(IntPtr.Zero);
            }

            // XXX - hack required to recognize exception types. These types
            // may need to be wrapped in old-style class wrappers in versions
            // of Python where new-style classes cannot be used as exceptions.

            if (Runtime.wrap_exceptions)
            {
                if (attr is ExceptionClassObject)
                {
                    ExceptionClassObject c = attr as ExceptionClassObject;
                    if (c != null)
                    {
                        IntPtr p = attr.pyHandle;
                        IntPtr r = Exceptions.GetExceptionClassWrapper(p);
                        Runtime.PyDict_SetItemString(self.dict, name, r);
                        Runtime.Incref(r);
                        return(r);
                    }
                }
            }

            Runtime.Incref(attr.pyHandle);
            return(attr.pyHandle);
        }
Beispiel #9
0
            public IncorrectRefCountException(IntPtr ptr)
            {
                PyPtr = ptr;
                IntPtr pyname = Runtime.PyObject_Unicode(PyPtr);
                string name   = Runtime.GetManagedString(pyname);

                Runtime.XDecref(pyname);
                _message = $"<{name}> may has a incorrect ref count";
            }
Beispiel #10
0
        public static string GetManagedString(IntPtr op)
        {
            string s;

            if (TryGetInterned(op, out s))
            {
                return(s);
            }
            return(Runtime.GetManagedString(op));
        }
Beispiel #11
0
        internal static IntPtr CreateSubType(IntPtr args)
        {
            IntPtr py_name = Runtime.PyTuple_GetItem(args, 0);
            IntPtr bases   = Runtime.PyTuple_GetItem(args, 1);
            IntPtr dict    = Runtime.PyTuple_GetItem(args, 2);
            IntPtr base_   = Runtime.PyTuple_GetItem(bases, 0);

            string name = Runtime.GetManagedString(py_name);
            IntPtr type = AllocateTypeObject(name);

            Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType);
            Runtime.Incref(Runtime.PyCLRMetaType);

            Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
            Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero);

            IntPtr offset = (IntPtr)ObjectOffset.ob_dict;

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

            IntPtr dc = Runtime.PyDict_Copy(dict);

            Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc);

            Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_);
            Runtime.Incref(base_);

            int flags = TypeFlags.Default;

            flags |= TypeFlags.Managed;
            flags |= TypeFlags.HeapType;
            flags |= TypeFlags.BaseType;
            flags |= TypeFlags.Subclass;
            flags |= TypeFlags.HaveGC;
            Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);

            CopySlot(base_, type, TypeOffset.tp_traverse);
            CopySlot(base_, type, TypeOffset.tp_clear);
            CopySlot(base_, type, TypeOffset.tp_is_gc);

            Runtime.PyType_Ready(type);


            IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
            IntPtr mod     = Runtime.PyString_FromString("CLR");

            Runtime.PyDict_SetItemString(tp_dict, "__module__", mod);

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

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

            return(type);
        }
Beispiel #12
0
        static void SetConversionError(IntPtr value, Type target)
        {
            IntPtr ob  = Runtime.PyObject_Repr(value);
            string src = Runtime.GetManagedString(ob);

            Runtime.Decref(ob);
            string error = String.Format(
                "Cannot convert {0} to {1}", src, target
                );

            Exceptions.SetError(Exceptions.TypeError, error);
        }
Beispiel #13
0
        private static void SetConversionError(IntPtr value, Type target)
        {
            // PyObject_Repr might clear the error
            Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace);

            IntPtr ob  = Runtime.PyObject_Repr(value);
            string src = Runtime.GetManagedString(ob);

            Runtime.XDecref(ob);

            Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable());
            Exceptions.RaiseTypeError($"Cannot convert {src} to {target}");
        }
Beispiel #14
0
        public new static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val)
        {
            var managedKey = Runtime.GetManagedString(key);

            if ((settableAttributes.Contains(managedKey)) ||
                (ManagedType.GetManagedObject(val)?.GetType() == typeof(ModuleObject)))
            {
                var self = (ModuleObject)ManagedType.GetManagedObject(ob);
                return(Runtime.PyDict_SetItem(self.dict, key, val));
            }

            return(ExtensionType.tp_setattro(ob, key, val));
        }
Beispiel #15
0
 private static bool IsLoadAll(BorrowedReference fromList)
 {
     if (CLRModule.preload)
     {
         return(false);
     }
     if (Runtime.PySequence_Size(fromList) != 1)
     {
         return(false);
     }
     using var fp = Runtime.PySequence_GetItem(fromList, 0);
     return(Runtime.GetManagedString(fp) == "*");
 }
Beispiel #16
0
        /// <summary>
        /// Bind the given Python instance and arguments to a particular method
        /// overload in <see cref="list"/> and return a structure that contains the converted Python
        /// instance, converted arguments and the correct method to call.
        /// If unsuccessful, may set a Python error.
        /// </summary>
        /// <param name="inst">The Python target of the method invocation.</param>
        /// <param name="args">The Python arguments.</param>
        /// <param name="kw">The Python keyword arguments.</param>
        /// <param name="info">If not null, only bind to that method.</param>
        /// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param>
        /// <returns>A Binding if successful.  Otherwise null.</returns>
        internal Binding?Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw, MethodBase?info, MethodBase[]?methodinfo)
        {
            // loop to find match, return invoker w/ or w/o error
            var kwargDict = new Dictionary <string, PyObject>();

            if (kw != null)
            {
                nint pynkwargs = Runtime.PyDict_Size(kw);
                using var keylist   = Runtime.PyDict_Keys(kw);
                using var valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(keylist.Borrow(), i));
                    BorrowedReference value = Runtime.PyList_GetItem(valueList.Borrow(), i);
                    kwargDict[keyStr !] = new PyObject(value);
Beispiel #17
0
        private void StoreSearchPaths()
        {
            var currentSysPath = GetSysPaths();

            _sysPaths = new List <string>();
            long itemsCount = currentSysPath.Length();

            for (long i = 0; i < itemsCount; i++)
            {
                BorrowedReference item =
                    CpyRuntime.PyList_GetItem(currentSysPath.Handle, i);
                string path = CpyRuntime.GetManagedString(item);
                _sysPaths.Add(path);
            }
        }
Beispiel #18
0
        public static void Print(string msg, BorrowedReference member)
        {
            string result = msg;

            result += " ";

            if (member == null)
            {
                Console.WriteLine("null arg to print");
            }
            using var ob = Runtime.PyObject_Repr(member);
            result      += Runtime.GetManagedString(ob.BorrowOrThrow());
            result      += " ";
            Console.WriteLine(result);
        }
Beispiel #19
0
        /// <summary>
        /// ModuleObject __getattribute__ implementation. Module attributes
        /// are always either classes or sub-modules representing subordinate
        /// namespaces. CLR modules implement a lazy pattern - the sub-modules
        /// and classes are created when accessed and cached for future use.
        /// </summary>
        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            var self = (ModuleObject)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                Exceptions.SetError(Exceptions.TypeError, "string expected");
                return(IntPtr.Zero);
            }

            IntPtr op = Runtime.PyDict_GetItem(self.dict, key);

            if (op != IntPtr.Zero)
            {
                Runtime.XIncref(op);
                return(op);
            }

            string name = Runtime.GetManagedString(key);

            if (name == "__dict__")
            {
                Runtime.XIncref(self.dict);
                return(self.dict);
            }

            ManagedType attr = null;

            try
            {
                attr = self.GetAttribute(name, true);
            }
            catch (Exception e)
            {
                Exceptions.SetError(e);
                return(IntPtr.Zero);
            }


            if (attr == null)
            {
                Exceptions.SetError(Exceptions.AttributeError, name);
                return(IntPtr.Zero);
            }

            Runtime.XIncref(attr.pyHandle);
            return(attr.pyHandle);
        }
Beispiel #20
0
        private static bool IsLoadAll(IntPtr fromList)
        {
            if (CLRModule.preload)
            {
                return(false);
            }
            if (Runtime.PySequence_Size(fromList) != 1)
            {
                return(false);
            }
            IntPtr fp  = Runtime.PySequence_GetItem(fromList, 0);
            bool   res = Runtime.GetManagedString(fp) == "*";

            Runtime.XDecref(fp);
            return(res);
        }
Beispiel #21
0
        private static bool IsLoadAll(BorrowedReference fromList)
        {
            if (fromList == null)
            {
                throw new ArgumentNullException(nameof(fromList));
            }

            if (CLRModule.preload)
            {
                return(false);
            }
            if (Runtime.PySequence_Size(fromList) != 1)
            {
                return(false);
            }
            using var fp = Runtime.PySequence_GetItem(fromList, 0);
            return(Runtime.GetManagedString(fp) == "*");
        }
Beispiel #22
0
        public static void Print(string msg, params IntPtr[] args)
        {
            string result = msg;

            result += " ";

            foreach (IntPtr t in args)
            {
                if (t == IntPtr.Zero)
                {
                    Console.WriteLine("null arg to print");
                }
                IntPtr ob = Runtime.PyObject_Repr(t);
                result += Runtime.GetManagedString(ob);
                Runtime.XDecref(ob);
                result += " ";
            }
            Console.WriteLine(result);
        }
Beispiel #23
0
        public static void Print(string msg, params IntPtr[] args)
        {
            string result = msg;

            result += " ";

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == IntPtr.Zero)
                {
                    Console.WriteLine("null arg to print");
                }
                IntPtr ob = Runtime.PyObject_Repr(args[i]);
                result += Runtime.GetManagedString(ob);
                Runtime.Decref(ob);
                result += " ";
            }
            Console.WriteLine(result);
            return;
        }
Beispiel #24
0
        /// <summary>
        /// Descriptor __getattribute__ implementation.
        /// </summary>
        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            var self = (MethodObject)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                return(Exceptions.RaiseTypeError("string expected"));
            }

            string name = Runtime.GetManagedString(key);

            if (name == "__doc__")
            {
                IntPtr doc = self.GetDocString();
                Runtime.XIncref(doc);
                return(doc);
            }

            return(Runtime.PyObject_GenericGetAttr(ob, key));
        }
Beispiel #25
0
        /// <summary>
        /// We __really__ want to avoid using Python objects or APIs when
        /// probing for assemblies to load, since our ResolveHandler may be
        /// called in contexts where we don't have the Python GIL and can't
        /// even safely try to get it without risking a deadlock ;(
        /// To work around that, we update a managed copy of sys.path (which
        /// is the main thing we care about) when UpdatePath is called. The
        /// import hook calls this whenever it knows its about to use the
        /// assembly manager, which lets us keep up with changes to sys.path
        /// in a relatively lightweight and low-overhead way.
        /// </summary>
        internal static void UpdatePath()
        {
            IntPtr list  = Runtime.Interop.PySys_GetObject("path");
            int    count = Runtime.Interop.PyList_Size(list);

            if (count != pypath.Count)
            {
                pypath.Clear();
                probed.Clear();
                for (var i = 0; i < count; i++)
                {
                    IntPtr item = Runtime.Interop.PyList_GetItem(list, i);
                    string path = Runtime.GetManagedString(item);
                    if (path != null)
                    {
                        pypath.Add(path);
                    }
                }
            }
        }
Beispiel #26
0
        public PythonException() : base()
        {
            Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB);
            Runtime.Incref(_pyType);
            Runtime.Incref(_pyValue);
            Runtime.Incref(_pyTB);
            IntPtr gs = PythonEngine.AcquireLock();

            if ((_pyType != IntPtr.Zero) && (_pyValue != IntPtr.Zero))
            {
                string type    = new PyObject(_pyType).GetAttr("__name__").ToString();
                string message = Runtime.GetManagedString(_pyValue);
                _message = type + " : " + message;
            }
            if (_pyTB != IntPtr.Zero)
            {
                PyObject tb_module = PythonEngine.ImportModule("traceback");
                _tb = tb_module.InvokeMethod("format_tb", new PyObject(_pyTB)).ToString();
            }
            PythonEngine.ReleaseLock(gs);
        }
Beispiel #27
0
        private static void SetConversionError(BorrowedReference value, Type target)
        {
            // PyObject_Repr might clear the error
            Runtime.PyErr_Fetch(out var causeType, out var causeVal, out var causeTrace);

            var    ob  = Runtime.PyObject_Repr(value);
            string src = "'object has no repr'";

            if (ob.IsNull())
            {
                Exceptions.Clear();
            }
            else
            {
                src = Runtime.GetManagedString(ob.Borrow()) ?? src;
            }
            ob.Dispose();

            Runtime.PyErr_Restore(causeType.StealNullable(), causeVal.StealNullable(), causeTrace.StealNullable());
            Exceptions.RaiseTypeError($"Cannot convert {src} to {target}");
        }
Beispiel #28
0
        /// <summary>
        /// Expose the wrapped implementation through attributes in both
        /// converted/encoded (__implementation__) and raw (__raw_implementation__) form.
        /// </summary>
        public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
        {
            var clrObj = (CLRObject)GetManagedObject(ob);

            if (!Runtime.PyString_Check(key))
            {
                return(Exceptions.RaiseTypeError("string expected"));
            }

            string name = Runtime.GetManagedString(key);

            if (name == "__implementation__")
            {
                return(Converter.ToPython(clrObj.inst));
            }
            else if (name == "__raw_implementation__")
            {
                return(CLRObject.GetInstHandle(clrObj.inst));
            }

            return(Runtime.PyObject_GenericGetAttr(ob, key));
        }
Beispiel #29
0
        protected static void AppendArgumentTypes(StringBuilder to, IntPtr args)
        {
            long argCount = Runtime.PyTuple_Size(args);

            to.Append("(");
            for (long argIndex = 0; argIndex < argCount; argIndex++)
            {
                var arg = Runtime.PyTuple_GetItem(args, argIndex);
                if (arg != IntPtr.Zero)
                {
                    var type = Runtime.PyObject_Type(arg);
                    if (type != IntPtr.Zero)
                    {
                        try
                        {
                            var description = Runtime.PyObject_Str(type);
                            if (description != IntPtr.Zero)
                            {
                                to.Append(Runtime.GetManagedString(description));
                                Runtime.XDecref(description);
                            }
                        }
                        finally
                        {
                            Runtime.XDecref(type);
                        }
                    }
                }

                if (argIndex + 1 < argCount)
                {
                    to.Append(", ");
                }
            }
            to.Append(')');
        }
Beispiel #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);
            }
        }