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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy