From c22d2f1a26c7610f8d8369585cf42d2fd2c44d66 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sat, 16 Oct 2021 11:01:52 -0700 Subject: [PATCH] fixed recursive dependency in clr module initialization when there's a public class that implements IEnumerable in global namespace https://github.com/pythonnet/pythonnet/issues/1601 the fix is to delay updating clr module dict with contents of .NET namespaces until after our internal modules are loaded --- src/embed_tests/pyimport.cs | 11 +++++++++++ src/runtime/importhook.cs | 25 ++++++++++++++++--------- src/runtime/pythonengine.cs | 7 ++++--- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/embed_tests/pyimport.cs b/src/embed_tests/pyimport.cs index f590ada4c..efb00cdcc 100644 --- a/src/embed_tests/pyimport.cs +++ b/src/embed_tests/pyimport.cs @@ -112,3 +112,14 @@ import clr } } } + +// regression for https://github.com/pythonnet/pythonnet/issues/1601 +// initialize fails if a class derived from IEnumerable is in global namespace +public class PublicEnumerator : System.Collections.IEnumerable +{ + public System.Collections.IEnumerator GetEnumerator() + { + return null; + } +} + diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index 0feb06b89..6675858fe 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics; namespace Python.Runtime { @@ -10,7 +11,14 @@ internal static class ImportHook { private static CLRModule root; private static IntPtr py_clr_module; - static BorrowedReference ClrModuleReference => new BorrowedReference(py_clr_module); + internal static BorrowedReference ClrModuleReference + { + get + { + Debug.Assert(py_clr_module != IntPtr.Zero); + return new BorrowedReference(py_clr_module); + } + } private const string LoaderCode = @" import importlib.abc @@ -43,7 +51,7 @@ def find_spec(klass, fullname, paths=None, target=None): return importlib.machinery.ModuleSpec(fullname, DotNetLoader(), is_package=True) return None "; - const string availableNsKey = "_available_namespaces"; + const string _available_namespaces = "_available_namespaces"; /// /// Initialization performed on startup of the Python runtime. @@ -154,12 +162,11 @@ static void SetupNamespaceTracking() { throw PythonException.ThrowLastAsClrException(); } - if (Runtime.PyDict_SetItemString(root.DictRef, availableNsKey, newset) != 0) - { - throw PythonException.ThrowLastAsClrException(); - } } - + if (Runtime.PyDict_SetItemString(root.DictRef, _available_namespaces, newset) != 0) + { + throw PythonException.ThrowLastAsClrException(); + } } /// @@ -168,7 +175,7 @@ static void SetupNamespaceTracking() static void TeardownNameSpaceTracking() { // If the C# runtime isn't loaded, then there are no namespaces available - Runtime.PyDict_SetItemString(root.dict, availableNsKey, Runtime.PyNone); + Runtime.PyDict_SetItemString(root.dict, _available_namespaces, Runtime.PyNone); } static readonly ConcurrentQueue addPending = new(); @@ -190,7 +197,7 @@ internal static void AddNamespaceWithGIL(string name) var pyNs = Runtime.PyString_FromString(name); try { - var nsSet = Runtime.PyDict_GetItemString(root.DictRef, availableNsKey); + var nsSet = Runtime.PyDict_GetItemString(root.DictRef, _available_namespaces); if (!(nsSet.IsNull || nsSet.DangerousGetAddress() == Runtime.PyNone)) { if (Runtime.PySet_Add(nsSet, new BorrowedReference(pyNs)) != 0) diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 10808a1cd..91e013e86 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -220,8 +220,7 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, } // Load the clr.py resource into the clr module - NewReference clr = Python.Runtime.ImportHook.GetCLRModule(); - BorrowedReference clr_dict = Runtime.PyModule_GetDict(clr); + BorrowedReference clr_dict = Runtime.PyModule_GetDict(ImportHook.ClrModuleReference); var locals = new PyDict(); try @@ -236,7 +235,7 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, LoadSubmodule(module_globals, "clr.interop", "interop.py"); - LoadMixins(module_globals); + LoadMixins(module_globals); // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. @@ -257,6 +256,8 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, { locals.Dispose(); } + + ImportHook.UpdateCLRModuleDict(); } static BorrowedReference DefineModule(string name) 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