1# Test the module type 2import unittest 3import weakref 4from test.support import gc_collect 5from test.support import import_helper 6from test.support.script_helper import assert_python_ok 7 8import sys 9ModuleType = type(sys) 10 11class FullLoader: 12 @classmethod 13 def module_repr(cls, m): 14 return "<module '{}' (crafted)>".format(m.__name__) 15 16class BareLoader: 17 pass 18 19 20class ModuleTests(unittest.TestCase): 21 def test_uninitialized(self): 22 # An uninitialized module has no __dict__ or __name__, 23 # and __doc__ is None 24 foo = ModuleType.__new__(ModuleType) 25 self.assertTrue(foo.__dict__ is None) 26 self.assertRaises(TypeError, dir, foo) 27 try: 28 s = foo.__name__ 29 self.fail("__name__ = %s" % repr(s)) 30 except AttributeError: 31 pass 32 self.assertEqual(foo.__doc__, ModuleType.__doc__) 33 34 def test_uninitialized_missing_getattr(self): 35 # Issue 8297 36 # test the text in the AttributeError of an uninitialized module 37 foo = ModuleType.__new__(ModuleType) 38 self.assertRaisesRegex( 39 AttributeError, "module has no attribute 'not_here'", 40 getattr, foo, "not_here") 41 42 def test_missing_getattr(self): 43 # Issue 8297 44 # test the text in the AttributeError 45 foo = ModuleType("foo") 46 self.assertRaisesRegex( 47 AttributeError, "module 'foo' has no attribute 'not_here'", 48 getattr, foo, "not_here") 49 50 def test_no_docstring(self): 51 # Regularly initialized module, no docstring 52 foo = ModuleType("foo") 53 self.assertEqual(foo.__name__, "foo") 54 self.assertEqual(foo.__doc__, None) 55 self.assertIs(foo.__loader__, None) 56 self.assertIs(foo.__package__, None) 57 self.assertIs(foo.__spec__, None) 58 self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None, 59 "__loader__": None, "__package__": None, 60 "__spec__": None}) 61 62 def test_ascii_docstring(self): 63 # ASCII docstring 64 foo = ModuleType("foo", "foodoc") 65 self.assertEqual(foo.__name__, "foo") 66 self.assertEqual(foo.__doc__, "foodoc") 67 self.assertEqual(foo.__dict__, 68 {"__name__": "foo", "__doc__": "foodoc", 69 "__loader__": None, "__package__": None, 70 "__spec__": None}) 71 72 def test_unicode_docstring(self): 73 # Unicode docstring 74 foo = ModuleType("foo", "foodoc\u1234") 75 self.assertEqual(foo.__name__, "foo") 76 self.assertEqual(foo.__doc__, "foodoc\u1234") 77 self.assertEqual(foo.__dict__, 78 {"__name__": "foo", "__doc__": "foodoc\u1234", 79 "__loader__": None, "__package__": None, 80 "__spec__": None}) 81 82 def test_reinit(self): 83 # Reinitialization should not replace the __dict__ 84 foo = ModuleType("foo", "foodoc\u1234") 85 foo.bar = 42 86 d = foo.__dict__ 87 foo.__init__("foo", "foodoc") 88 self.assertEqual(foo.__name__, "foo") 89 self.assertEqual(foo.__doc__, "foodoc") 90 self.assertEqual(foo.bar, 42) 91 self.assertEqual(foo.__dict__, 92 {"__name__": "foo", "__doc__": "foodoc", "bar": 42, 93 "__loader__": None, "__package__": None, "__spec__": None}) 94 self.assertTrue(foo.__dict__ is d) 95 96 def test_dont_clear_dict(self): 97 # See issue 7140. 98 def f(): 99 foo = ModuleType("foo") 100 foo.bar = 4 101 return foo 102 gc_collect() 103 self.assertEqual(f().__dict__["bar"], 4) 104 105 def test_clear_dict_in_ref_cycle(self): 106 destroyed = [] 107 m = ModuleType("foo") 108 m.destroyed = destroyed 109 s = """class A: 110 def __init__(self, l): 111 self.l = l 112 def __del__(self): 113 self.l.append(1) 114a = A(destroyed)""" 115 exec(s, m.__dict__) 116 del m 117 gc_collect() 118 self.assertEqual(destroyed, [1]) 119 120 def test_weakref(self): 121 m = ModuleType("foo") 122 wr = weakref.ref(m) 123 self.assertIs(wr(), m) 124 del m 125 gc_collect() 126 self.assertIs(wr(), None) 127 128 def test_module_getattr(self): 129 import test.good_getattr as gga 130 from test.good_getattr import test 131 self.assertEqual(test, "There is test") 132 self.assertEqual(gga.x, 1) 133 self.assertEqual(gga.y, 2) 134 with self.assertRaisesRegex(AttributeError, 135 "Deprecated, use whatever instead"): 136 gga.yolo 137 self.assertEqual(gga.whatever, "There is whatever") 138 del sys.modules['test.good_getattr'] 139 140 def test_module_getattr_errors(self): 141 import test.bad_getattr as bga 142 from test import bad_getattr2 143 self.assertEqual(bga.x, 1) 144 self.assertEqual(bad_getattr2.x, 1) 145 with self.assertRaises(TypeError): 146 bga.nope 147 with self.assertRaises(TypeError): 148 bad_getattr2.nope 149 del sys.modules['test.bad_getattr'] 150 if 'test.bad_getattr2' in sys.modules: 151 del sys.modules['test.bad_getattr2'] 152 153 def test_module_dir(self): 154 import test.good_getattr as gga 155 self.assertEqual(dir(gga), ['a', 'b', 'c']) 156 del sys.modules['test.good_getattr'] 157 158 def test_module_dir_errors(self): 159 import test.bad_getattr as bga 160 from test import bad_getattr2 161 with self.assertRaises(TypeError): 162 dir(bga) 163 with self.assertRaises(TypeError): 164 dir(bad_getattr2) 165 del sys.modules['test.bad_getattr'] 166 if 'test.bad_getattr2' in sys.modules: 167 del sys.modules['test.bad_getattr2'] 168 169 def test_module_getattr_tricky(self): 170 from test import bad_getattr3 171 # these lookups should not crash 172 with self.assertRaises(AttributeError): 173 bad_getattr3.one 174 with self.assertRaises(AttributeError): 175 bad_getattr3.delgetattr 176 if 'test.bad_getattr3' in sys.modules: 177 del sys.modules['test.bad_getattr3'] 178 179 def test_module_repr_minimal(self): 180 # reprs when modules have no __file__, __name__, or __loader__ 181 m = ModuleType('foo') 182 del m.__name__ 183 self.assertEqual(repr(m), "<module '?'>") 184 185 def test_module_repr_with_name(self): 186 m = ModuleType('foo') 187 self.assertEqual(repr(m), "<module 'foo'>") 188 189 def test_module_repr_with_name_and_filename(self): 190 m = ModuleType('foo') 191 m.__file__ = '/tmp/foo.py' 192 self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") 193 194 def test_module_repr_with_filename_only(self): 195 m = ModuleType('foo') 196 del m.__name__ 197 m.__file__ = '/tmp/foo.py' 198 self.assertEqual(repr(m), "<module '?' from '/tmp/foo.py'>") 199 200 def test_module_repr_with_loader_as_None(self): 201 m = ModuleType('foo') 202 assert m.__loader__ is None 203 self.assertEqual(repr(m), "<module 'foo'>") 204 205 def test_module_repr_with_bare_loader_but_no_name(self): 206 m = ModuleType('foo') 207 del m.__name__ 208 # Yes, a class not an instance. 209 m.__loader__ = BareLoader 210 loader_repr = repr(BareLoader) 211 self.assertEqual( 212 repr(m), "<module '?' ({})>".format(loader_repr)) 213 214 def test_module_repr_with_full_loader_but_no_name(self): 215 # m.__loader__.module_repr() will fail because the module has no 216 # m.__name__. This exception will get suppressed and instead the 217 # loader's repr will be used. 218 m = ModuleType('foo') 219 del m.__name__ 220 # Yes, a class not an instance. 221 m.__loader__ = FullLoader 222 loader_repr = repr(FullLoader) 223 self.assertEqual( 224 repr(m), "<module '?' ({})>".format(loader_repr)) 225 226 def test_module_repr_with_bare_loader(self): 227 m = ModuleType('foo') 228 # Yes, a class not an instance. 229 m.__loader__ = BareLoader 230 module_repr = repr(BareLoader) 231 self.assertEqual( 232 repr(m), "<module 'foo' ({})>".format(module_repr)) 233 234 def test_module_repr_with_full_loader(self): 235 m = ModuleType('foo') 236 # Yes, a class not an instance. 237 m.__loader__ = FullLoader 238 self.assertEqual( 239 repr(m), "<module 'foo' (crafted)>") 240 241 def test_module_repr_with_bare_loader_and_filename(self): 242 # Because the loader has no module_repr(), use the file name. 243 m = ModuleType('foo') 244 # Yes, a class not an instance. 245 m.__loader__ = BareLoader 246 m.__file__ = '/tmp/foo.py' 247 self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") 248 249 def test_module_repr_with_full_loader_and_filename(self): 250 # Even though the module has an __file__, use __loader__.module_repr() 251 m = ModuleType('foo') 252 # Yes, a class not an instance. 253 m.__loader__ = FullLoader 254 m.__file__ = '/tmp/foo.py' 255 self.assertEqual(repr(m), "<module 'foo' (crafted)>") 256 257 def test_module_repr_builtin(self): 258 self.assertEqual(repr(sys), "<module 'sys' (built-in)>") 259 260 def test_module_repr_source(self): 261 r = repr(unittest) 262 starts_with = "<module 'unittest' from '" 263 ends_with = "__init__.py'>" 264 self.assertEqual(r[:len(starts_with)], starts_with, 265 '{!r} does not start with {!r}'.format(r, starts_with)) 266 self.assertEqual(r[-len(ends_with):], ends_with, 267 '{!r} does not end with {!r}'.format(r, ends_with)) 268 269 def test_module_finalization_at_shutdown(self): 270 # Module globals and builtins should still be available during shutdown 271 rc, out, err = assert_python_ok("-c", "from test import final_a") 272 self.assertFalse(err) 273 lines = out.splitlines() 274 self.assertEqual(set(lines), { 275 b"x = a", 276 b"x = b", 277 b"final_a.x = a", 278 b"final_b.x = b", 279 b"len = len", 280 b"shutil.rmtree = rmtree"}) 281 282 def test_descriptor_errors_propagate(self): 283 class Descr: 284 def __get__(self, o, t): 285 raise RuntimeError 286 class M(ModuleType): 287 melon = Descr() 288 self.assertRaises(RuntimeError, getattr, M("mymod"), "melon") 289 290 def test_lazy_create_annotations(self): 291 # module objects lazy create their __annotations__ dict on demand. 292 # the annotations dict is stored in module.__dict__. 293 # a freshly created module shouldn't have an annotations dict yet. 294 foo = ModuleType("foo") 295 for i in range(4): 296 self.assertFalse("__annotations__" in foo.__dict__) 297 d = foo.__annotations__ 298 self.assertTrue("__annotations__" in foo.__dict__) 299 self.assertEqual(foo.__annotations__, d) 300 self.assertEqual(foo.__dict__['__annotations__'], d) 301 if i % 2: 302 del foo.__annotations__ 303 else: 304 del foo.__dict__['__annotations__'] 305 306 def test_setting_annotations(self): 307 foo = ModuleType("foo") 308 for i in range(4): 309 self.assertFalse("__annotations__" in foo.__dict__) 310 d = {'a': int} 311 foo.__annotations__ = d 312 self.assertTrue("__annotations__" in foo.__dict__) 313 self.assertEqual(foo.__annotations__, d) 314 self.assertEqual(foo.__dict__['__annotations__'], d) 315 if i % 2: 316 del foo.__annotations__ 317 else: 318 del foo.__dict__['__annotations__'] 319 320 def test_annotations_getset_raises(self): 321 # module has no dict, all operations fail 322 foo = ModuleType.__new__(ModuleType) 323 with self.assertRaises(TypeError): 324 print(foo.__annotations__) 325 with self.assertRaises(TypeError): 326 foo.__annotations__ = {} 327 with self.assertRaises(TypeError): 328 del foo.__annotations__ 329 330 # double delete 331 foo = ModuleType("foo") 332 foo.__annotations__ = {} 333 del foo.__annotations__ 334 with self.assertRaises(AttributeError): 335 del foo.__annotations__ 336 337 def test_annotations_are_created_correctly(self): 338 ann_module4 = import_helper.import_fresh_module('test.ann_module4') 339 self.assertTrue("__annotations__" in ann_module4.__dict__) 340 del ann_module4.__annotations__ 341 self.assertFalse("__annotations__" in ann_module4.__dict__) 342 343 344 # frozen and namespace module reprs are tested in importlib. 345 346 347if __name__ == '__main__': 348 unittest.main() 349