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