@@ -26,25 +26,64 @@ internal static void InitializeModuleDef()
26
26
#endif
27
27
28
28
/// <summary>
29
- /// Initialization performed on startup of the Python runtime .
29
+ /// Get a <i>New reference</i> to the builtins module .
30
30
/// </summary>
31
- internal static void Initialize ( )
31
+ static IntPtr GetNewRefToBuiltins ( )
32
32
{
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 ( ) ;
38
41
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
+ }
42
48
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__" ) ;
44
59
hook = new MethodWrapper ( typeof ( ImportHook ) , "__import__" , "TernaryFunc" ) ;
45
- Runtime . PyObject_SetAttrString ( mod , "__import__" , hook . ptr ) ;
60
+ Runtime . PyObject_SetAttrString ( builtins , "__import__" , hook . ptr ) ;
46
61
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 ( ) ;
47
85
86
+ // Initialize the clr module and tell Python about it.
48
87
root = new CLRModule ( ) ;
49
88
50
89
#if PYTHON3
@@ -62,6 +101,7 @@ internal static void Initialize()
62
101
Runtime . XIncref ( root . pyHandle ) ; // we are using the module two times
63
102
py_clr_module = root . pyHandle ; // Alias handle for PY2/PY3
64
103
#endif
104
+ IntPtr dict = Runtime . PyImport_GetModuleDict ( ) ;
65
105
Runtime . PyDict_SetItemString ( dict , "CLR" , py_clr_module ) ;
66
106
Runtime . PyDict_SetItemString ( dict , "clr" , py_clr_module ) ;
67
107
}
@@ -74,9 +114,10 @@ internal static void Shutdown()
74
114
{
75
115
if ( Runtime . Py_IsInitialized ( ) != 0 )
76
116
{
117
+ RestoreImport ( ) ;
118
+
77
119
Runtime . XDecref ( py_clr_module ) ;
78
120
Runtime . XDecref ( root . pyHandle ) ;
79
- Runtime . XDecref ( py_import ) ;
80
121
}
81
122
}
82
123
0 commit comments