Repository navigation
Use importlib for __import__ - #2122
Conversation
BCSharp
left a comment
There was a problem hiding this comment.
I see that this is work in progress, but here are my findings so far after playing with it for a while.
| // anything unusual goes through _gcd_import for its errors | ||
| try { | ||
| module = PythonOps.Invoke(context, bootstrap, "_gcd_import", absName); | ||
| } catch (ImportException e) when (level == 0 && !modName.Contains('.') |
There was a problem hiding this comment.
Consider this:
>>> import clr
>>> g = clr.GetCurrentRuntime().Globals
>>> import sys
>>> sys.modules['blocked_name'] = None
>>> import blocked_name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2222, in _gcd_import
ImportError: import of blocked_name halted; None in sys.modules
>>> g.blocked_name = 42
>>> import blocked_name
>>> sys.modules['blocked_name']
42Looks like a regression. ImportError is expected in both cases.
| int firstDot = modName.IndexOf('.'); | ||
| int cutOff = firstDot == -1 ? 0 : modName.Length - firstDot; | ||
| string topName = absName.Substring(0, absName.Length - cutOff); | ||
| if (!modules.TryGetValue(topName, out top)) { | ||
| throw PythonOps.KeyError($"{PythonOps.Repr(context, topName)} not in sys.modules as expected"); | ||
| } |
There was a problem hiding this comment.
# assume packages p, p.a, p.a.b already exist
import p.a.b
import sys
sys.modules['p.a'] = None
__import__("a.b", {"__package__": "p"}, None, None, 1)
# CPython: None (value of sys.modules['p.a'])
# IronPython: ImportError: No module named 'a.b'Perhaps setting top = module when firstDot == -1?
|
Ran into a complication for which I'm undecided. Using |
I had a similar dilemma with codecs: in case of a name conflict, prefer .NET codecs or Python installed codecs? In the end I thought it's better to give precedence to .NET, since IronPython is a .NET language. Perhaps with an option to override in some obscure scenarios. In case of import, I think it is less problematic as conflicts should be rare. The convention for .NET is names capitalized, and for Python 3 it is all lowercase. |
Use
importlibfor__import__. Includes fast paths written in C# so performance should be similar to what we had before. The legacy mechanism is still available with the (debug-only)-X NoImportLiboption.Breaking changes:
PalImporterto re-enable this as a follow-up PR)importlib.invalidate_caches()is called, like CPythonimportlib._bootstrap, custom importers now follow CPython semantics (find_specis preferred overfind_module, etc.)ImportErrorifsitecan't be found (use-Sto skip)Follow up items:
ImportModuleWithImportLib:ShowClsat the import statement, like__future__clr.AddReferenceoutside of__import__