diff options
author | Brett Cannon <brett@python.org> | 2016-01-15 21:33:03 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2016-01-15 21:33:03 (GMT) |
commit | 63b8505281f9c26f7304b3e00d658b429b862d5b (patch) | |
tree | 07a4d20ed327d8493aa7105bec9ca1d598cc6b7c /Lib | |
parent | 43cfd8240c274b2f4cf0588f3defae83e7379a55 (diff) | |
download | cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.zip cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.tar.gz cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.tar.bz2 |
Issue #25791: Raise an ImportWarning when __spec__ or __package__ are
not defined for a relative import.
This is the start of work to try and clean up import semantics to rely
more on a module's spec than on the myriad attributes that get set on
a module. Thanks to Rose Ames for the patch.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 6 | ||||
-rw-r--r-- | Lib/test/test_importlib/import_/test___package__.py | 40 |
2 files changed, 32 insertions, 14 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 6f62bb3..9adcf7b 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1032,8 +1032,14 @@ def _calc___package__(globals): to represent that its proper value is unknown. """ + spec = globals.get('__spec__') + if spec is not None: + return spec.parent package = globals.get('__package__') if package is None: + _warnings.warn("can't resolve package from __spec__ or __package__, " + "falling back on __name__ and __path__", + ImportWarning, stacklevel=3) package = globals['__name__'] if '__path__' not in globals: package = package.rpartition('.')[0] diff --git a/Lib/test/test_importlib/import_/test___package__.py b/Lib/test/test_importlib/import_/test___package__.py index c7d3a2a..08e41c9 100644 --- a/Lib/test/test_importlib/import_/test___package__.py +++ b/Lib/test/test_importlib/import_/test___package__.py @@ -33,31 +33,39 @@ class Using__package__: """ - def test_using___package__(self): - # [__package__] + def import_module(self, globals_): with self.mock_modules('pkg.__init__', 'pkg.fake') as importer: with util.import_state(meta_path=[importer]): self.__import__('pkg.fake') module = self.__import__('', - globals={'__package__': 'pkg.fake'}, + globals=globals_, fromlist=['attr'], level=2) + return module + + def test_using___package__(self): + # [__package__] + module = self.import_module({'__package__': 'pkg.fake'}) self.assertEqual(module.__name__, 'pkg') - def test_using___name__(self, package_as_None=False): + def test_using___name__(self): # [__name__] - globals_ = {'__name__': 'pkg.fake', '__path__': []} - if package_as_None: - globals_['__package__'] = None - with self.mock_modules('pkg.__init__', 'pkg.fake') as importer: - with util.import_state(meta_path=[importer]): - self.__import__('pkg.fake') - module = self.__import__('', globals= globals_, - fromlist=['attr'], level=2) - self.assertEqual(module.__name__, 'pkg') + module = self.import_module({'__name__': 'pkg.fake', '__path__': []}) + self.assertEqual(module.__name__, 'pkg') + + def test_warn_when_using___name__(self): + with self.assertWarns(ImportWarning): + self.import_module({'__name__': 'pkg.fake', '__path__': []}) def test_None_as___package__(self): # [None] - self.test_using___name__(package_as_None=True) + module = self.import_module({ + '__name__': 'pkg.fake', '__path__': [], '__package__': None }) + self.assertEqual(module.__name__, 'pkg') + + def test_prefers___spec__(self): + globals = {'__spec__': FakeSpec()} + with self.assertRaises(SystemError): + self.__import__('', globals, {}, ['relimport'], 1) def test_bad__package__(self): globals = {'__package__': '<not real>'} @@ -70,6 +78,10 @@ class Using__package__: self.__import__('', globals, {}, ['relimport'], 1) +class FakeSpec: + parent = '<fake>' + + class Using__package__PEP302(Using__package__): mock_modules = util.mock_modules |