| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 73958ed commit e71a0ef
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,7 +19,7 @@ import sys | |||
| 19 | 19 | class DotNetLoader(importlib.abc.Loader): | |
| 20 | 20 | ||
| 21 | 21 | def __init__(self): | |
| 22 | - super(DotNetLoader, self).__init__() | ||
| 22 | + super().__init__() | ||
| 23 | 23 | ||
| 24 | 24 | @classmethod | |
| 25 | 25 | def exec_module(klass, mod): | |
@@ -29,21 +29,19 @@ def exec_module(klass, mod): | |||
| 29 | 29 | @classmethod | |
| 30 | 30 | def create_module(klass, spec): | |
| 31 | 31 | import clr | |
| 32 | - return clr._LoadClrModule(spec) | ||
| 32 | + return clr._load_clr_module(spec) | ||
| 33 | 33 | ||
| 34 | 34 | class DotNetFinder(importlib.abc.MetaPathFinder): | |
| 35 | 35 | ||
| 36 | 36 | def __init__(self): | |
| 37 | - super(DotNetFinder, self).__init__() | ||
| 37 | + super().__init__() | ||
| 38 | 38 | ||
| 39 | 39 | @classmethod | |
| 40 | 40 | def find_spec(klass, fullname, paths=None, target=None): | |
| 41 | 41 | import clr | |
| 42 | - if (hasattr(clr, '_availableNamespaces') and fullname in clr._availableNamespaces): | ||
| 42 | + if clr._availableNamespaces and fullname in clr._availableNamespaces: | ||
| 43 | 43 | return importlib.machinery.ModuleSpec(fullname, DotNetLoader(), is_package=True) | |
| 44 | 44 | return None | |
| 45 | - | ||
| 46 | - sys.meta_path.append(DotNetFinder()) | ||
| 47 | 45 | "; | |
| 48 | 46 | const string availableNsKey = "_availableNamespaces"; | |
| 49 | 47 | ||
@@ -69,7 +67,7 @@ internal static unsafe void Initialize() | |||
| 69 | 67 | ||
| 70 | 68 | // Add/create the MetaPathLoader | |
| 71 | 69 | SetupNamespaceTracking(); | |
| 72 | - PythonEngine.Exec(LoaderCode); | ||
| 70 | + SetupImportHook(); | ||
| 73 | 71 | } | |
| 74 | 72 | ||
| 75 | 73 | ||
@@ -114,13 +112,66 @@ internal static void RestoreRuntimeData(RuntimeDataStorage storage) | |||
| 114 | 112 | SetupNamespaceTracking(); | |
| 115 | 113 | } | |
| 116 | 114 | ||
| 115 | + static void SetupImportHook() | ||
| 116 | + { | ||
| 117 | + // Create the import hook module | ||
| 118 | + var import_hook_module_def = ModuleDefOffset.AllocModuleDef("clr.loader"); | ||
| 119 | + var import_hook_module = Runtime.PyModule_Create2(import_hook_module_def, 3); | ||
| 120 | + | ||
| 121 | + // Run the python code to create the module's classes. | ||
| 122 | + var mod_dict = Runtime.PyModule_GetDict(new BorrowedReference(import_hook_module)); | ||
| 123 | + var builtins = Runtime.PyEval_GetBuiltins(); | ||
| 124 | + var exec = Runtime.PyDict_GetItemString(builtins, "exec"); | ||
| 125 | + using var args = NewReference.DangerousFromPointer(Runtime.PyTuple_New(2)); | ||
| 126 | + | ||
| 127 | + var codeStr = Runtime.PyString_FromString(LoaderCode); | ||
| 128 | + Runtime.PyTuple_SetItem(args.DangerousGetAddress(), 0, codeStr); | ||
| 129 | + // PyTuple_SetItem steals a reference, mod_dict is borrowed. | ||
| 130 | + Runtime.XIncref(mod_dict.DangerousGetAddress()); | ||
| 131 | + Runtime.PyTuple_SetItem(args.DangerousGetAddress(), 1, mod_dict.DangerousGetAddress()); | ||
| 132 | + Runtime.PyObject_Call(exec.DangerousGetAddress(), args.DangerousGetAddress(), IntPtr.Zero); | ||
| 133 | + | ||
| 134 | + var loader = Runtime.PyDict_GetItemString(mod_dict, "DotNetLoader").DangerousGetAddressOrNull(); | ||
| 135 | + Runtime.XIncref(loader); | ||
| 136 | + | ||
| 137 | + // Add the classes to the module | ||
| 138 | + // PyModule_AddObject steals a reference only on success | ||
| 139 | + if (Runtime.PyModule_AddObject(import_hook_module, "DotNetLoader", loader) != 0) | ||
| 140 | + { | ||
| 141 | + Runtime.XDecref(loader); | ||
| 142 | + throw new PythonException(); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + var finder = Runtime.PyDict_GetItemString(mod_dict, "DotNetFinder").DangerousGetAddressOrNull(); | ||
| 146 | + Runtime.XIncref(finder); | ||
| 147 | + if (Runtime.PyModule_AddObject(import_hook_module, "DotNetFinder", finder) != 0) | ||
| 148 | + { | ||
| 149 | + Runtime.XDecref(finder); | ||
| 150 | + throw new PythonException(); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + // Set as a sub-module of clr. | ||
| 154 | + Runtime.XIncref(import_hook_module); | ||
| 155 | + if(Runtime.PyModule_AddObject(py_clr_module, "loader", import_hook_module) != 0) | ||
| 156 | + { | ||
| 157 | + Runtime.XDecref(import_hook_module); | ||
| 158 | + throw new PythonException(); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + // Finally, add the hook to the meta path | ||
| 162 | + var finder_inst = Runtime.PyDict_GetItemString(mod_dict, "finder_inst").DangerousGetAddressOrNull(); | ||
| 163 | + Runtime.XIncref(finder); | ||
| 164 | + var metapath = Runtime.PySys_GetObject("meta_path"); | ||
| 165 | + Runtime.PyList_Append(metapath, finder); | ||
| 166 | + } | ||
| 167 | + | ||
| 117 | 168 | /// <summary> | |
| 118 | 169 | /// Sets up the tracking of loaded namespaces. This makes available to | |
| 119 | 170 | /// Python, as a Python object, the loaded namespaces. The set of loaded | |
| 120 | 171 | /// namespaces is used during the import to verify if we can import a | |
| 121 | 172 | /// CLR assembly as a module or not. The set is stored on the clr module. | |
| 122 | 173 | /// </summary> | |
| 123 | - static void SetupNamespaceTracking () | ||
| 174 | + static void SetupNamespaceTracking() | ||
| 124 | 175 | { | |
| 125 | 176 | var newset = Runtime.PySet_New(new BorrowedReference(IntPtr.Zero)); | |
| 126 | 177 | try | |
@@ -130,7 +181,7 @@ static void SetupNamespaceTracking () | |||
| 130 | 181 | var pyNs = Runtime.PyString_FromString(ns); | |
| 131 | 182 | try | |
| 132 | 183 | { | |
| 133 | - if(Runtime.PySet_Add(newset, new BorrowedReference(pyNs)) != 0) | ||
| 184 | + if (Runtime.PySet_Add(newset, new BorrowedReference(pyNs)) != 0) | ||
| 134 | 185 | { | |
| 135 | 186 | throw new PythonException(); | |
| 136 | 187 | } | |
@@ -141,7 +192,7 @@ static void SetupNamespaceTracking () | |||
| 141 | 192 | } | |
| 142 | 193 | } | |
| 143 | 194 | ||
| 144 | - if(Runtime.PyDict_SetItemString(root.dict, availableNsKey, newset.DangerousGetAddress()) != 0) | ||
| 195 | + if (Runtime.PyDict_SetItemString(root.dict, availableNsKey, newset.DangerousGetAddress()) != 0) | ||
| 145 | 196 | { | |
| 146 | 197 | throw new PythonException(); | |
| 147 | 198 | } | |
@@ -152,7 +203,7 @@ static void SetupNamespaceTracking () | |||
| 152 | 203 | } | |
| 153 | 204 | ||
| 154 | 205 | AssemblyManager.namespaceAdded += OnNamespaceAdded; | |
| 155 | - PythonEngine.AddShutdownHandler(()=>AssemblyManager.namespaceAdded -= OnNamespaceAdded); | ||
| 206 | + PythonEngine.AddShutdownHandler(() => AssemblyManager.namespaceAdded -= OnNamespaceAdded); | ||
| 156 | 207 | } | |
| 157 | 208 | ||
| 158 | 209 | /// <summary> | |
@@ -162,27 +213,21 @@ static void SetupNamespaceTracking () | |||
| 162 | 213 | static void TeardownNameSpaceTracking() | |
| 163 | 214 | { | |
| 164 | 215 | AssemblyManager.namespaceAdded -= OnNamespaceAdded; | |
| 165 | - // If the C# runtime isn't loaded, then there is no namespaces available | ||
| 166 | - if ((Runtime.PyDict_DelItemString(new BorrowedReference(root.dict), availableNsKey) != 0) && | ||
| 167 | - (Exceptions.ExceptionMatches(Exceptions.KeyError))) | ||
| 168 | - { | ||
| 169 | - // Trying to remove a key that's not in the dictionary | ||
| 170 | - // raises an error. We don't care about it. | ||
| 171 | - Runtime.PyErr_Clear(); | ||
| 172 | - } | ||
| 216 | + // If the C# runtime isn't loaded, then there are no namespaces available | ||
| 217 | + Runtime.PyDict_SetItemString(root.dict, availableNsKey, Runtime.PyNone); | ||
| 173 | 218 | } | |
| 174 | 219 | ||
| 175 | - static void OnNamespaceAdded (string name) | ||
| 220 | + static void OnNamespaceAdded(string name) | ||
| 176 | 221 | { | |
| 177 | - using(Py.GIL()) | ||
| 222 | + using (Py.GIL()) | ||
| 178 | 223 | { | |
| 179 | 224 | var pyNs = Runtime.PyString_FromString(name); | |
| 180 | 225 | try | |
| 181 | 226 | { | |
| 182 | 227 | var nsSet = Runtime.PyDict_GetItemString(new BorrowedReference(root.dict), availableNsKey); | |
| 183 | - if (!nsSet.IsNull) | ||
| 228 | + if (!nsSet.IsNull || nsSet.DangerousGetAddress() != Runtime.PyNone) | ||
| 184 | 229 | { | |
| 185 | - if(Runtime.PySet_Add(nsSet, new BorrowedReference(pyNs)) != 0) | ||
| 230 | + if (Runtime.PySet_Add(nsSet, new BorrowedReference(pyNs)) != 0) | ||
| 186 | 231 | { | |
| 187 | 232 | throw new PythonException(); | |
| 188 | 233 | } | |
@@ -225,7 +270,7 @@ public static unsafe NewReference GetCLRModule() | |||
| 225 | 270 | /// <summary> | |
| 226 | 271 | /// The hook to import a CLR module into Python | |
| 227 | 272 | /// </summary> | |
| 228 | - public static ModuleObject __import__(string modname) | ||
| 273 | + public static ModuleObject Import(string modname) | ||
| 229 | 274 | { | |
| 230 | 275 | // Traverse the qualified module name to get the named module. | |
| 231 | 276 | // Note that if | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -593,12 +593,12 @@ public static int _AtExit() | |||
| 593 | 593 | /// <returns>A new reference to the imported module, as a PyObject.</returns> | |
| 594 | 594 | [ModuleFunction] | |
| 595 | 595 | [ForbidPythonThreads] | |
| 596 | - public static PyObject _LoadClrModule(PyObject spec) | ||
| 596 | + public static PyObject _load_clr_module(PyObject spec) | ||
| 597 | 597 | { | |
| 598 | 598 | ModuleObject mod = null; | |
| 599 | 599 | using (var modname = spec.GetAttr("name")) | |
| 600 | 600 | { | |
| 601 | - mod = ImportHook.__import__(modname.ToString()); | ||
| 601 | + mod = ImportHook.Import(modname.ToString()); | ||
| 602 | 602 | } | |
| 603 | 603 | // We can't return directly a ModuleObject, because the tpHandle is | |
| 604 | 604 | // not set, but we can return a PyObject. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -160,7 +160,7 @@ static void ValidateRequiredOffsetsPresent(PropertyInfo[] offsetProperties) | |||
| 160 | 160 | "getPreload", | |
| 161 | 161 | "Initialize", | |
| 162 | 162 | "ListAssemblies", | |
| 163 | - "_LoadClrModule", | ||
| 163 | + "_load_clr_module", | ||
| 164 | 164 | "Release", | |
| 165 | 165 | "Reset", | |
| 166 | 166 | "set_SuppressDocs", | |
| Back | FazBrowse Home | New Git URL |
0 commit comments