New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
relative import without parent succeeds with builtins.__import__ #81590
Comments
The second line should raise an ImportError but instead succeeds (tested cpython 3.6.7, 3.7.0 and 3.7.3, and from interactive interpreter and scripts). Specifically, builtins.__import__ does not reproduce the behaviour of importlib._bootstrap.__import__; maybe ceval.c:import_from is neglecting to check that there are parent packages when attempting a relative import? More details here: https://stackoverflow.com/a/56768129/5104777 |
I can't reproduce: >>> from importlib import abc
>>> from . import util
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'util' from '__main__' (unknown location)
>>> import importlib.util
>>> Did you happen to do an |
>>> foo = 'oops'
>>> from . import foo as fubar # should raise ImportError
>>> fubar
'oops' After further investigation, the problem is that builtins.__import__ (the c port version) does not replicate the behaviour of importlib.__import__ (the python reference version): >>> import builtins, importlib
>>> __package__ is None
True
>>> importlib.__import__('', globals(), locals(), ('foo',), 1)
ImportError
>>> builtins.__import__('', globals(), locals(), ('foo',), 1)
<module '__main__' (built-in)> A further discrepancy is that for deeper relative imports, builtins.__import__ raises a ValueError instead of ImportError (contrary to expectation/spec): >>> from ...... import foo
ValueError A simple work around uses the python implementation to restore expected behaviour: >>> builtins.__import__ = importlib.__import__
>>> from ...... import foo
ImportError
>>> from curses import ascii
>>> from . import ascii
ImportError PS: Brett Cannon, to replicate please copy and paste lines in correct order :-) |
Please open a separate issue for the relative import issue. |
I opened bpo-37444 for the relative import beyond top-level package issue. |
The code doing the sanity check for importlib can be found at cpython/Lib/importlib/_bootstrap.py Lines 943 to 948 in f9f8e3c
|
If you run with >>> builtins.__import__('', globals(), locals(), ('foo',), 1)
<stdin>:1: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
<module '__main__' (built-in)> The check is being done in resolve_name() in import.c ( Line 1543 in f9f8e3c
|
I'll look into this further and open a PR initially for the regression tests. |
The test added seems to have created an ImportWarning in test_builtin.BuiltinTest.test_import . ./python.exe -Wall -m unittest -v test.test_builtin.BuiltinTest.test_import ---------------------------------------------------------------------- OK |
The test is same as below and given that __spec__ an __name__ are passed as None where ImportWarning is raised in Lib/importlib/_bootstrap.py 1074 . can we just use self.assertWarns(ImportWarning) in the test? >>> __import__('', {'__package__': None, '__spec__': None, '__name__': '__main__'}, locals={}, fromlist=('foo',), level=1)
<stdin>:1: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: attempted relative import with no known parent package |
Thanks for catching the warning and the fix, Karthikeyan! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: