8000 (WIP) import hook in the pytohn module · pythonnet/pythonnet@4684523 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 4684523

Browse files
committed
(WIP) import hook in the pytohn module
1 parent ab5d99e commit 4684523

File tree

6 files changed

+49
-15
lines changed

6 files changed

+49
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ or the DLL must be loaded in advance. This must be done before calling any other
4040
- Sign Runtime DLL with a strong name
4141
- Implement loading through `clr_loader` instead of the included `ClrModule`, enables
4242
support for .NET Core
43-
- Replaced the old `__import__` hook hack with a PEP302-style Meta Path Loade
43+
- BREAKING: Replaced the old `__import__` hook hack with a PEP302-style Meta Path Loader. Because the
44+
new loader is implemented in python, the `pythonnet` python module must be in `sys.path` or in `PYTHONPATH`.
4445

4546
### Fixed
4647

pythonnet/util/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .find_libpython import find_libpython
1+
from ..find_libpython import find_libpython

pythonnet/util/import_hook.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import importlib.abc
2+
import sys
3+
4+
class DotNetLoader(importlib.abc.Loader):
5+
6+
def __init__(self):
7+
super(DotNetLoader, self).__init__()
8+
9+
@classmethod
10+
def exec_module(klass, mod):
11+
# This method needs to exist.
12+
pass
13+
14+
@classmethod
15+
def create_module(klass, spec):
16+
import clr
17+
return clr._LoadClrModule(spec)
18+
19+
class DotNetFinder(importlib.abc.MetaPathFinder):
20+
21+
def __init__(self):
22+
super(DotNetFinder, self).__init__()
23+
24+
@classmethod
25+
def find_spec(klass, fullname, paths=None, target=None):
26+
import clr
27+
if (hasattr(clr, '_availableNamespaces') and fullname in clr._availableNamespaces):
28+
return importlib.machinery.ModuleSpec(fullname, DotNetLoader(), is_package=True)
29+
return None
30+
31+
32+
def init_import_hook():
33+
sys.meta_path.append(DotNetFinder())

src/runtime/importhook.cs

Lines changed: 2 additions & 2 deletions

src/runtime/moduleobject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ internal static unsafe void Initialize()
9090

9191
// Add/create the MetaPathLoader
9292
SetupNamespaceTracking();
93-
PythonEngine.Exec(LoaderCode);
93+
PythonEngine.Exec("import pythonnet.util.import_hook;pythonnet.util.import_hook.init_import_hook()");
9494
}
9595

9696

@@ -250,7 +250,7 @@ public static unsafe NewReference GetCLRModule()
250250
/// <summary>
251251
/// The hook to import a CLR module into Python
252252
/// </summary>
253-
public static ModuleObject __import__(string modname)
253+
public static ModuleObject Import(string modname)
254254
{
255255
// Traverse the qualified module name to get the named module.
256256
// Note that if
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ public static PyObject _LoadClrModule(PyObject spec)
600600
ModuleObject mod = null;
601601
using (var modname = spec.GetAttr("name"))
602602
{
603-
mod = ImportHook.__import__(modname.ToString());
603+
mod = ImportHook.Import(modname.ToString());
604604
}
605605
// We can't return directly a ModuleObject, because the tpHandle is
606606
// not set, but we can return a PyObject.

src/runtime/runtime.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
154154
ClassDerivedObject.Reset();
155155
TypeManager.Initialize();
156156

157+
// Need to add the runtime directory to sys.path so that we
158+
// can find built-in assemblies like System.Data, et. al.
159+
string rtdir = RuntimeEnvironment.GetRuntimeDirectory();
160+
IntPtr path = PySys_GetObject("path").DangerousGetAddress();
161+
IntPtr item = PyString_FromString(rtdir);
162+
if (PySequence_Contains(path, item) == 0)
163+
{
164+
PyList_Append(new BorrowedReference(path), item);
165+
}
166+
XDecref(item);
157167
// Initialize modules that depend on the runtime class.
158168
AssemblyManager.Initialize();
159169
OperatorMethod.Initialize();
@@ -168,16 +178,6 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
168178
}
169179
Exceptions.Initialize();
170180

171-
// Need to add the runtime directory to sys.path so that we
172-
// can find built-in assemblies like System.Data, et. al.
173-
string rtdir = RuntimeEnvironment.GetRuntimeDirectory();
174-
IntPtr path = PySys_GetObject("path").DangerousGetAddress();
175-
IntPtr item = PyString_FromString(rtdir);
176-
if (PySequence_Contains(path, item) == 0)
177-
{
178-
PyList_Append(new BorrowedReference(path), item);
179-
}
180-
XDecref(item);
181181
AssemblyManager.UpdatePath();
182182
}
183183

0 commit comments

Comments
 (0)
0