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

Skip to content

Commit 3f335db

Browse files
committed
fixed recursive dependency in clr module initialization when there's a public class that implements IEnumerable in global namespace
#1601 the fix is to delay updating clr module dict with contents of .NET namespaces until after our internal modules are loaded
1 parent bc3265d commit 3f335db

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

src/embed_tests/pyimport.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,14 @@ import clr
112112
}
113113
}
114114
}
115+
116+
// regression for https://github.com/pythonnet/pythonnet/issues/1601
117+
// initialize fails if a class derived from IEnumerable is in global namespace
118+
public class PublicEnumerator : System.Collections.IEnumerable
119+
{
120+
public System.Collections.IEnumerator GetEnumerator()
121+
{
122+
return null;
123+
}
124+
}
125+

src/runtime/importhook.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
3+
using System.Diagnostics;
34

45
namespace Python.Runtime
56
{
@@ -10,7 +11,14 @@ internal static class ImportHook
1011
{
1112
private static CLRModule root;
1213
private static IntPtr py_clr_module;
13-
static BorrowedReference ClrModuleReference => new BorrowedReference(py_clr_module);
14+
internal static BorrowedReference ClrModuleReference
15+
{
16+
get
17+
{
18+
Debug.Assert(py_clr_module != IntPtr.Zero);
19+
return new BorrowedReference(py_clr_module);
20+
}
21+
}
1422

1523
private const string LoaderCode = @"
1624
import importlib.abc
@@ -43,7 +51,7 @@ def find_spec(klass, fullname, paths=None, target=None):
4351
return importlib.machinery.ModuleSpec(fullname, DotNetLoader(), is_package=True)
4452
return None
4553
";
46-
const string availableNsKey = "_available_namespaces";
54+
const string _available_namespaces = "_available_namespaces";
4755

4856
/// <summary>
4957
/// Initialization performed on startup of the Python runtime.
@@ -154,12 +162,11 @@ static void SetupNamespaceTracking()
154162
{
155163
throw PythonException.ThrowLastAsClrException();
156164
}
157-
if (Runtime.PyDict_SetItemString(root.DictRef, availableNsKey, newset) != 0)
158-
{
159-
throw PythonException.ThrowLastAsClrException();
160-
}
161165
}
162-
166+
if (Runtime.PyDict_SetItemString(root.DictRef, _available_namespaces, newset) != 0)
167+
{
168+
throw PythonException.ThrowLastAsClrException();
169+
}
163170
}
164171

165172
/// <summary>
@@ -168,7 +175,7 @@ static void SetupNamespaceTracking()
168175
static void TeardownNameSpaceTracking()
169176
{
170177
// If the C# runtime isn't loaded, then there are no namespaces available
171-
Runtime.PyDict_SetItemString(root.dict, availableNsKey, Runtime.PyNone);
178+
Runtime.PyDict_SetItemString(root.dict, _available_namespaces, Runtime.PyNone);
172179
}
173180

174181
static readonly ConcurrentQueue<string> addPending = new();
@@ -190,7 +197,7 @@ internal static void AddNamespaceWithGIL(string name)
190197
var pyNs = Runtime.PyString_FromString(name);
191198
try
192199
{
193-
var nsSet = Runtime.PyDict_GetItemString(root.DictRef, availableNsKey);
200+
var nsSet = Runtime.PyDict_GetItemString(root.DictRef, _available_namespaces);
194201
if (!(nsSet.IsNull || nsSet.DangerousGetAddress() == Runtime.PyNone))
195202
{
196203
if (Runtime.PySet_Add(nsSet, new BorrowedReference(pyNs)) != 0)

src/runtime/pythonengine.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,7 @@ public static void Initialize(IEnumerable<string> args, bool setSysArgv = true,
220220
}
221221

222222
// Load the clr.py resource into the clr module
223-
NewReference clr = Python.Runtime.ImportHook.GetCLRModule();
224-
BorrowedReference clr_dict = Runtime.PyModule_GetDict(clr);
223+
BorrowedReference clr_dict = Runtime.PyModule_GetDict(ImportHook.ClrModuleReference);
225224

226225
var locals = new PyDict();
227226
try
@@ -236,7 +235,7 @@ public static void Initialize(IEnumerable<string> args, bool setSysArgv = true,
236235

237236
LoadSubmodule(module_globals, "clr.interop", "interop.py");
238237

239-
LoadMixins(module_globals);
238+
LoadMixins(module_globals);
240239

241240
// add the imported module to the clr module, and copy the API functions
242241
// and decorators into the main clr module.
@@ -257,6 +256,8 @@ public static void Initialize(IEnumerable<string> args, bool setSysArgv = true,
257256
{
258257
locals.Dispose();
259258
}
259+
260+
ImportHook.UpdateCLRModuleDict();
260261
}
261262

262263
static BorrowedReference DefineModule(string name)

0 commit comments

Comments
 (0)