1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
"""PEP 366 ("Main module explicit relative imports") specifies the
semantics for the __package__ attribute on modules. This attribute is
used, when available, to detect which package a module belongs to (instead
of using the typical __path__/__name__ test).
"""
import unittest
from .. import util
class Using__package__:
"""Use of __package__ supercedes the use of __name__/__path__ to calculate
what package a module belongs to. The basic algorithm is [__package__]::
def resolve_name(name, package, level):
level -= 1
base = package.rsplit('.', level)[0]
return '{0}.{1}'.format(base, name)
But since there is no guarantee that __package__ has been set (or not been
set to None [None]), there has to be a way to calculate the attribute's value
[__name__]::
def calc_package(caller_name, has___path__):
if has__path__:
return caller_name
else:
return caller_name.rsplit('.', 1)[0]
Then the normal algorithm for relative name imports can proceed as if
__package__ had been set.
"""
def test_using___package__(self):
# [__package__]
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'},
fromlist=['attr'], level=2)
self.assertEqual(module.__name__, 'pkg')
def test_using___name__(self, package_as_None=False):
# [__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')
def test_None_as___package__(self):
# [None]
self.test_using___name__(package_as_None=True)
def test_bad__package__(self):
globals = {'__package__': '<not real>'}
with self.assertRaises(SystemError):
self.__import__('', globals, {}, ['relimport'], 1)
def test_bunk__package__(self):
globals = {'__package__': 42}
with self.assertRaises(TypeError):
self.__import__('', globals, {}, ['relimport'], 1)
class Using__package__PEP302(Using__package__):
mock_modules = util.mock_modules
(Frozen_UsingPackagePEP302,
Source_UsingPackagePEP302
) = util.test_both(Using__package__PEP302, __import__=util.__import__)
class Using__package__PEP451(Using__package__):
mock_modules = util.mock_spec
(Frozen_UsingPackagePEP451,
Source_UsingPackagePEP451
) = util.test_both(Using__package__PEP451, __import__=util.__import__)
class Setting__package__:
"""Because __package__ is a new feature, it is not always set by a loader.
Import will set it as needed to help with the transition to relying on
__package__.
For a top-level module, __package__ is set to None [top-level]. For a
package __name__ is used for __package__ [package]. For submodules the
value is __name__.rsplit('.', 1)[0] [submodule].
"""
__import__ = util.__import__['Source']
# [top-level]
def test_top_level(self):
with self.mock_modules('top_level') as mock:
with util.import_state(meta_path=[mock]):
del mock['top_level'].__package__
module = self.__import__('top_level')
self.assertEqual(module.__package__, '')
# [package]
def test_package(self):
with self.mock_modules('pkg.__init__') as mock:
with util.import_state(meta_path=[mock]):
del mock['pkg'].__package__
module = self.__import__('pkg')
self.assertEqual(module.__package__, 'pkg')
# [submodule]
def test_submodule(self):
with self.mock_modules('pkg.__init__', 'pkg.mod') as mock:
with util.import_state(meta_path=[mock]):
del mock['pkg.mod'].__package__
pkg = self.__import__('pkg.mod')
module = getattr(pkg, 'mod')
self.assertEqual(module.__package__, 'pkg')
class Setting__package__PEP302(Setting__package__, unittest.TestCase):
mock_modules = util.mock_modules
class Setting__package__PEP451(Setting__package__, unittest.TestCase):
mock_modules = util.mock_spec
if __name__ == '__main__':
unittest.main()
|