Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5f2e2e2

Browse files
benoithudsonfilmor
authored andcommitted
Split from PR 958: restoring the __import__ after shutdown. (pythonnet#993)
When C# shuts down we should restore Python to its original state.
1 parent 2736094 commit 5f2e2e2

File tree

1 file changed

+54
-13
lines changed

1 file changed

+54
-13
lines changed

src/runtime/importhook.cs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,64 @@ internal static void InitializeModuleDef()
2626
#endif
2727

2828
/// <summary>
29-
/// Initialization performed on startup of the Python runtime.
29+
/// Get a <i>New reference</i> to the builtins module.
3030
/// </summary>
31-
internal static void Initialize()
31+
static IntPtr GetNewRefToBuiltins()
3232
{
33-
// Initialize the Python <--> CLR module hook. We replace the
34-
// built-in Python __import__ with our own. This isn't ideal,
35-
// but it provides the most "Pythonic" way of dealing with CLR
36-
// modules (Python doesn't provide a way to emulate packages).
37-
IntPtr dict = Runtime.PyImport_GetModuleDict();
33+
if (Runtime.IsPython3)
34+
{
35+
return Runtime.PyImport_ImportModule("builtins");
36+
}
37+
else
38+
{
39+
// dict is a borrowed ref, no need to decref
40+
IntPtr dict = Runtime.PyImport_GetModuleDict();
3841

39-
IntPtr mod = Runtime.IsPython3
40-
? Runtime.PyImport_ImportModule("builtins")
41-
: Runtime.PyDict_GetItemString(dict, "__builtin__");
42+
// GetItemString is a borrowed ref; incref to get a new ref
43+
IntPtr builtins = Runtime.PyDict_GetItemString(dict, "__builtin__");
44+
Runtime.XIncref(builtins);
45+
return builtins;
46+
}
47+
}
4248

43-
py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
49+
/// <summary>
50+
/// Initialize just the __import__ hook itself.
51+
/// </summary>
52+
static void InitImport()
53+
{
54+
// We replace the built-in Python __import__ with our own: first
55+
// look in CLR modules, then if we don't find any call the default
56+
// Python __import__.
57+
IntPtr builtins = GetNewRefToBuiltins();
58+
py_import = Runtime.PyObject_GetAttrString(builtins, "__import__");
4459
hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
45-
Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
60+
Runtime.PyObject_SetAttrString(builtins, "__import__", hook.ptr);
4661
Runtime.XDecref(hook.ptr);
62+
Runtime.XDecref(builtins);
63+
}
64+
65+
/// <summary>
66+
/// Restore the __import__ hook.
67+
/// </summary>
68+
static void RestoreImport()
69+
{
70+
IntPtr builtins = GetNewRefToBuiltins();
71+
72+
Runtime.PyObject_SetAttrString(builtins, "__import__", py_import);
73+
Runtime.XDecref(py_import);
74+
py_import = IntPtr.Zero;
75+
76+
Runtime.XDecref(builtins);
77+
}
78+
79+
/// <summary>
80+
/// Initialization performed on startup of the Python runtime.
81+
/// </summary>
82+
internal static void Initialize()
83+
{
84+
InitImport();
4785

86+
// Initialize the clr module and tell Python about it.
4887
root = new CLRModule();
4988

5089
#if PYTHON3
@@ -62,6 +101,7 @@ internal static void Initialize()
62101
Runtime.XIncref(root.pyHandle); // we are using the module two times
63102
py_clr_module = root.pyHandle; // Alias handle for PY2/PY3
64103
#endif
104+
IntPtr dict = Runtime.PyImport_GetModuleDict();
65105
Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module);
66106
Runtime.PyDict_SetItemString(dict, "clr", py_clr_module);
67107
}
@@ -74,9 +114,10 @@ internal static void Shutdown()
74114
{
75115
if (Runtime.Py_IsInitialized() != 0)
76116
{
117+
RestoreImport();
118+
77119
Runtime.XDecref(py_clr_module);
78120
Runtime.XDecref(root.pyHandle);
79-
Runtime.XDecref(py_import);
80121
}
81122
}
82123

0 commit comments

Comments
 (0)