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
bpo-37409: fix relative import with no parent #14956
Conversation
…ere no package exists Relative imports use resolve_name to get the absolute target name, which first seeks the current module's absolute package name from the globals: If __package__ (and __spec__.parent) are missing then as a hail mary it uses __name__, truncating the last segment if the module is any submodule rather than a package __init__.py (which it guesses from whether __path__ is defined). The hail mary should fail if there is no parent package (top level modules), if __name__ is uninformatively '__main__' (-m entry points), or both (scripts). That is, if both __name__ has no subcomponents and the module does not seem to be a package __init__ module. (Bug silently used module as if package, aliasing unexpected objects. Note importlib contained an unaffected alternative __import__ implementation.)
This is a conservative (minimal) change, intended to also be appropriate for back-porting. The bug was that (sibling-level) relative import statements would in some cases (when unable to identify any enclosing package) instead retrieve objects from the current module rather than raising the expected ImportError. (Only Specifically, the problem concerned circumstances where |
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Co-Authored-By: Brett Cannon <54418+brettcannon@users.noreply.github.com>
Co-Authored-By: Brett Cannon <54418+brettcannon@users.noreply.github.com>
Co-Authored-By: Brett Cannon <54418+brettcannon@users.noreply.github.com>
Co-Authored-By: Brett Cannon <54418+brettcannon@users.noreply.github.com>
I have made the requested changes; please review again |
Thanks for making the requested changes! @brettcannon: please review the changes made to this pull request. |
Misc/NEWS.d/next/Core and Builtins/2019-08-06-23-39-05.bpo-37409.1qwzn2.rst
Outdated
Show resolved
Hide resolved
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Co-Authored-By: Brett Cannon <54418+brettcannon@users.noreply.github.com>
@brettcannon is this also appropriate for backporting to 3.7? I hope this fix may help people encounter more informative error messages when they are first learning/experimenting with explicit relative imports (say, migrating code from py2). I have made the requested changes; please review again |
Thanks for making the requested changes! @brettcannon: please review the changes made to this pull request. |
Thanks @benjimin for the PR, and @brettcannon for merging it |
@brettcannon: Please replace |
Sorry, @benjimin and @brettcannon, I could not cleanly backport this to |
Sorry @benjimin and @brettcannon, I had trouble checking out the |
GH-15913 is a backport of this pull request to the 3.8 branch. |
) Relative imports use resolve_name to get the absolute target name, which first seeks the current module's absolute package name from the globals: If __package__ (and __spec__.parent) are missing then import uses __name__, truncating the last segment if the module is a submodule rather than a package __init__.py (which it guesses from whether __path__ is defined). The __name__ attempt should fail if there is no parent package (top level modules), if __name__ is '__main__' (-m entry points), or both (scripts). That is, if both __name__ has no subcomponents and the module does not seem to be a package __init__ module then import should fail.. (cherry picked from commit 92420b3) Co-authored-by: Ben Lewis <benjimin@users.noreply.github.com>
…ythonGH-15913) Relative imports use resolve_name to get the absolute target name, which first seeks the current module's absolute package name from the globals: If __package__ (and __spec__.parent) are missing then import uses __name__, truncating the last segment if the module is a submodule rather than a package __init__.py (which it guesses from whether __path__ is defined). The __name__ attempt should fail if there is no parent package (top level modules), if __name__ is '__main__' (-m entry points), or both (scripts). That is, if both __name__ has no subcomponents and the module does not seem to be a package __init__ module then import should fail.. (cherry picked from commit 92420b3) Co-authored-by: Ben Lewis <benjimin@users.noreply.github.com> (cherry picked from commit 0a6693a) Co-authored-by: Brett Cannon <54418+brettcannon@users.noreply.github.com>
#15925 is the 3.7 backport |
) Relative imports use resolve_name to get the absolute target name, which first seeks the current module's absolute package name from the globals: If __package__ (and __spec__.parent) are missing then import uses __name__, truncating the last segment if the module is a submodule rather than a package __init__.py (which it guesses from whether __path__ is defined). The __name__ attempt should fail if there is no parent package (top level modules), if __name__ is '__main__' (-m entry points), or both (scripts). That is, if both __name__ has no subcomponents and the module does not seem to be a package __init__ module then import should fail.. (cherry picked from commit 92420b3) Co-authored-by: Ben Lewis <benjimin@users.noreply.github.com> (cherry picked from commit 0a6693a) Co-authored-by: Brett Cannon <54418+brettcannon@users.noreply.github.com>
And all the backports are done! Thanks, @benjimin . |
Relative imports use resolve_name to get the absolute target name, which first seeks the current module's absolute package name from the globals: If __package__ (and __spec__.parent) are missing then import uses __name__, truncating the last segment if the module is a submodule rather than a package __init__.py (which it guesses from whether __path__ is defined). The __name__ attempt should fail if there is no parent package (top level modules), if __name__ is '__main__' (-m entry points), or both (scripts). That is, if both __name__ has no subcomponents and the module does not seem to be a package __init__ module then import should fail.
builtins.__import__
was missing a check to flag that if no dot was found in the__name__
of a module that isn't explicitly a submodule of a package then a relative import is incorrect.https://bugs.python.org/issue37409