summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2016-01-15 21:33:03 (GMT)
committerBrett Cannon <brett@python.org>2016-01-15 21:33:03 (GMT)
commit63b8505281f9c26f7304b3e00d658b429b862d5b (patch)
tree07a4d20ed327d8493aa7105bec9ca1d598cc6b7c /Lib
parent43cfd8240c274b2f4cf0588f3defae83e7379a55 (diff)
downloadcpython-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.py6
-rw-r--r--Lib/test/test_importlib/import_/test___package__.py40
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