From b8a1b1583992c685d70c8ea4c3f092f9035121e6 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Nov 2020 11:21:11 -0800 Subject: [PATCH 1/2] minor improvement to debugging experience --- src/runtime/pythonexception.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 893bd9491..1e10967d7 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -250,6 +250,7 @@ public static bool Matches(IntPtr ob) return Runtime.PyErr_ExceptionMatches(ob) != 0; } + [System.Diagnostics.DebuggerHidden] public static void ThrowIfIsNull(IntPtr ob) { if (ob == IntPtr.Zero) @@ -258,6 +259,7 @@ public static void ThrowIfIsNull(IntPtr ob) } } + [System.Diagnostics.DebuggerHidden] internal static void ThrowIfIsNull(BorrowedReference reference) { if (reference.IsNull) @@ -266,6 +268,7 @@ internal static void ThrowIfIsNull(BorrowedReference reference) } } + [System.Diagnostics.DebuggerHidden] public static void ThrowIfIsNotZero(int value) { if (value != 0) From 1747b42bd760f5429e5b2b31c36fa9413bac71f0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Nov 2020 11:23:15 -0800 Subject: [PATCH 2/2] Remove deprecated implicit assembly loading Legacy behavior: `import Company.Product.Namespace` would search for `Company.Product.Namespace.dll` .NET assmebly, load it, and import the namespace. New behavior: User must always explicitly add assembly reference using `clr.AddReference` to `Company.Product.Namespace` prior to attempting import --- CHANGELOG.md | 4 ++ src/runtime/assemblymanager.cs | 69 ---------------------------------- src/runtime/importhook.cs | 32 ---------------- src/runtime/moduleobject.cs | 24 ------------ src/tests/test_array.py | 3 ++ src/tests/test_class.py | 4 ++ src/tests/test_compat.py | 3 ++ src/tests/test_module.py | 14 +++---- 8 files changed, 21 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d27c136a3..8f6185b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,10 @@ details about the cause of the failure - Fixed a bug where indexers could not be used if they were inherited - Made it possible to use `__len__` also on `ICollection<>` interface objects +### Removed + +- implicit assembly loading (you have to explicitly `clr.AddReference` before doing import) + ## [2.5.0][] - 2020-06-14 This version improves performance on benchmarks significantly compared to 2.3. diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index ba6faa076..01ccf6957 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -252,75 +252,6 @@ public static Assembly FindLoadedAssembly(string name) return null; } - /// - /// Given a qualified name of the form A.B.C.D, attempt to load - /// an assembly named after each of A.B.C.D, A.B.C, A.B, A. This - /// will only actually probe for the assembly once for each unique - /// namespace. Returns true if any assemblies were loaded. - /// - /// - /// TODO item 3 "* Deprecate implicit loading of assemblies": - /// Set the fromFile flag if the name of the loaded assembly matches - /// the fully qualified name that was requested if the framework - /// actually loads an assembly. - /// Call ONLY for namespaces that HAVE NOT been cached yet. - /// - public static bool LoadImplicit(string name, Action assemblyLoadErrorHandler, bool warn = true) - { - string[] names = name.Split('.'); - var loaded = false; - var s = ""; - Assembly lastAssembly = null; - HashSet assembliesSet = null; - for (var i = 0; i < names.Length; i++) - { - s = i == 0 ? names[0] : s + "." + names[i]; - if (!probed.ContainsKey(s)) - { - if (assembliesSet == null) - { - assembliesSet = new HashSet(AppDomain.CurrentDomain.GetAssemblies()); - } - Assembly a = FindLoadedAssembly(s); - try - { - if (a == null) - { - a = LoadAssemblyPath(s); - } - - if (a == null) - { - a = LoadAssembly(s); - } - } - catch (FileLoadException e) { assemblyLoadErrorHandler(e); } - catch (BadImageFormatException e) { assemblyLoadErrorHandler(e); } - catch (System.Security.SecurityException e) { assemblyLoadErrorHandler(e); } - catch (PathTooLongException e) { assemblyLoadErrorHandler(e); } - - if (a != null && !assembliesSet.Contains(a)) - { - loaded = true; - lastAssembly = a; - } - probed[s] = 1; - } - } - - // Deprecation warning - if (warn && loaded) - { - string location = Path.GetFileNameWithoutExtension(lastAssembly.Location); - string deprWarning = "The module was found, but not in a referenced namespace.\n" + - $"Implicit loading is deprecated. Please use clr.AddReference('{location}')."; - Exceptions.deprecation(deprWarning); - } - - return loaded; - } - - /// /// Scans an assembly for exported namespaces, adding them to the /// mapping of valid namespaces. Note that for a given namespace diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index e2795e4e3..3f318fd1c 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -310,38 +310,6 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) string[] names = realname.Split('.'); - // Now we need to decide if the name refers to a CLR module, - // and may have to do an implicit load (for b/w compatibility) - // using the AssemblyManager. The assembly manager tries - // really hard not to use Python objects or APIs, because - // parts of it can run recursively and on strange threads. - // - // It does need an opportunity from time to time to check to - // see if sys.path has changed, in a context that is safe. Here - // we know we have the GIL, so we'll let it update if needed. - - AssemblyManager.UpdatePath(); - if (!AssemblyManager.IsValidNamespace(realname)) - { - var loadExceptions = new List(); - if (!AssemblyManager.LoadImplicit(realname, assemblyLoadErrorHandler: loadExceptions.Add)) - { - // May be called when a module being imported imports a module. - // In particular, I've seen decimal import copy import org.python.core - IntPtr importResult = Runtime.PyObject_Call(py_import, args, kw); - // TODO: use ModuleNotFoundError in Python 3.6+ - if (importResult == IntPtr.Zero && loadExceptions.Count > 0 - && Exceptions.ExceptionMatches(Exceptions.ImportError)) - { - loadExceptions.Add(new PythonException()); - var importError = new PyObject(new BorrowedReference(Exceptions.ImportError)); - importError.SetAttr("__cause__", new AggregateException(loadExceptions).ToPython()); - Runtime.PyErr_SetObject(new BorrowedReference(Exceptions.ImportError), importError.Reference); - } - return importResult; - } - } - // See if sys.modules for this interpreter already has the // requested module. If so, just return the existing module. IntPtr modules = Runtime.PyImport_GetModuleDict(); diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index c7085d18a..334c5c2f3 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -118,30 +118,6 @@ public ManagedType GetAttribute(string name, bool guess) return c; } - // This is a little repetitive, but it ensures that the right - // thing happens with implicit assembly loading at a reasonable - // cost. Ask the AssemblyManager to do implicit loading for each - // of the steps in the qualified name, then try it again. - bool ignore = name.StartsWith("__"); - if (AssemblyManager.LoadImplicit(qname, assemblyLoadErrorHandler: ImportWarning, !ignore)) - { - if (AssemblyManager.IsValidNamespace(qname)) - { - m = new ModuleObject(qname); - StoreAttribute(name, m); - m.DecrRefCount(); - return m; - } - - type = AssemblyManager.LookupTypes(qname).FirstOrDefault(t => t.IsPublic); - if (type != null) - { - c = ClassManager.GetClass(type); - StoreAttribute(name, c); - return c; - } - } - // We didn't find the name, so we may need to see if there is a // generic type with this base name. If so, we'll go ahead and // return it. Note that we store the mapping of the unmangled diff --git a/src/tests/test_array.py b/src/tests/test_array.py index 015b5bdde..428bb2065 100644 --- a/src/tests/test_array.py +++ b/src/tests/test_array.py @@ -2,6 +2,7 @@ """Test support for managed arrays.""" +import clr import Python.Test as Test import System import pytest @@ -1143,6 +1144,8 @@ def test_boxed_value_type_mutation_result(): # to accidentally write code like the following which is not really # mutating value types in-place but changing boxed copies. + clr.AddReference('System.Drawing') + from System.Drawing import Point from System import Array diff --git a/src/tests/test_class.py b/src/tests/test_class.py index c24d788df..4666631f7 100644 --- a/src/tests/test_class.py +++ b/src/tests/test_class.py @@ -3,6 +3,7 @@ """Test CLR class support.""" +import clr import Python.Test as Test import System import pytest @@ -124,6 +125,9 @@ def __init__(self, v): def test_struct_construction(): """Test construction of structs.""" + + clr.AddReference('System.Drawing') + from System.Drawing import Point p = Point() diff --git a/src/tests/test_compat.py b/src/tests/test_compat.py index 1c9f80e65..ec36e3be0 100644 --- a/src/tests/test_compat.py +++ b/src/tests/test_compat.py @@ -3,6 +3,7 @@ """Backward-compatibility tests for deprecated features.""" +import clr import types import pytest @@ -137,6 +138,8 @@ def test_dotted_name_import_from_with_alias(): def test_from_module_import_star(): """Test from module import * behavior.""" + clr.AddReference('System.Management') + count = len(locals().keys()) m = __import__('CLR.System.Management', globals(), locals(), ['*']) assert m.__name__ == 'System.Management' diff --git a/src/tests/test_module.py b/src/tests/test_module.py index 2b1a9e4ec..dcdb0248e 100644 --- a/src/tests/test_module.py +++ b/src/tests/test_module.py @@ -192,6 +192,8 @@ def test_dotted_name_import_from_with_alias(): def test_from_module_import_star(): """Test from module import * behavior.""" + clr.AddReference('System.Xml') + count = len(locals().keys()) m = __import__('System.Xml', globals(), locals(), ['*']) assert m.__name__ == 'System.Xml' @@ -201,16 +203,14 @@ def test_from_module_import_star(): def test_implicit_assembly_load(): """Test implicit assembly loading via import.""" - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") + with pytest.raises(ImportError): + # MS.Build should not have been added as a reference yet + # (and should exist for mono) - # should trigger a DeprecationWarning as Microsoft.Build hasn't - # been added as a reference yet (and should exist for mono) + # The implicit behavior has been disabled in 3.0 + # therefore this should fail import Microsoft.Build - assert len(w) == 1 - assert isinstance(w[0].message, DeprecationWarning) - with warnings.catch_warnings(record=True) as w: clr.AddReference("System.Windows.Forms") import System.Windows.Forms as Forms 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