1# Test the module type 2import unittest 3import weakref 4from test.support import gc_collect, requires_type_collecting 5from test.support.script_helper import assert_python_ok 6 7import sys 8ModuleType = type(sys) 9 10class FullLoader: 11 @classmethod 12 def module_repr(cls, m): 13 return "<module '{}' (crafted)>".format(m.__name__) 14 15class BareLoader: 16 pass 17 18 19class ModuleTests(unittest.TestCase): 20 def test_uninitialized(self): 21 # An uninitialized module has no __dict__ or __name__, 22 # and __doc__ is None 23 foo = ModuleType.__new__(ModuleType) 24 self.assertTrue(foo.__dict__ is None) 25 self.assertRaises(SystemError, dir, foo) 26 try: 27 s = foo.__name__ 28 self.fail("__name__ = %s" % repr(s)) 29 except AttributeError: 30 pass 31 self.assertEqual(foo.__doc__, ModuleType.__doc__) 32 33 def test_uninitialized_missing_getattr(self): 34 # Issue 8297 35 # test the text in the AttributeError of an uninitialized module 36 foo = ModuleType.__new__(ModuleType) 37 self.assertRaisesRegex( 38 AttributeError, "module has no attribute 'not_here'", 39 getattr, foo, "not_here") 40 41 def test_missing_getattr(self): 42 # Issue 8297 43 # test the text in the AttributeError 44 foo = ModuleType("foo") 45 self.assertRaisesRegex( 46 AttributeError, "module 'foo' has no attribute 'not_here'", 47 getattr, foo, "not_here") 48 49 def test_no_docstring(self): 50 # Regularly initialized module, no docstring 51 foo = ModuleType("foo") 52 self.assertEqual(foo.__name__, "foo") 53 self.assertEqual(foo.__doc__, None) 54 self.assertIs(foo.__loader__, None) 55 self.assertIs(foo.__package__, None) 56 self.assertIs(foo.__spec__, None) 57 self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None, 58 "__loader__": None, "__package__": None, 59 "__spec__": None}) 60 61 def test_ascii_docstring(self): 62 # ASCII docstring 63 foo = ModuleType("foo", "foodoc") 64 self.assertEqual(foo.__name__, "foo") 65 self.assertEqual(foo.__doc__, "foodoc") 66 self.assertEqual(foo.__dict__, 67 {"__name__": "foo", "__doc__": "foodoc", 68 "__loader__": None, "__package__": None, 69 "__spec__": None}) 70 71 def test_unicode_docstring(self): 72 # Unicode docstring 73 foo = ModuleType("foo", "foodoc\u1234") 74 self.assertEqual(foo.__name__, "foo") 75 self.assertEqual(foo.__doc__, "foodoc\u1234") 76 self.assertEqual(foo.__dict__, 77 {"__name__": "foo", "__doc__": "foodoc\u1234", 78 "__loader__": None, "__package__": None, 79 "__spec__": None}) 80 81 def test_reinit(self): 82 # Reinitialization should not replace the __dict__ 83 foo = ModuleType("foo", "foodoc\u1234") 84 foo.bar = 42 85 d = foo.__dict__ 86 foo.__init__("foo", "foodoc") 87 self.assertEqual(foo.__name__, "foo") 88 self.assertEqual(foo.__doc__, "foodoc") 89 self.assertEqual(foo.bar, 42) 90 self.assertEqual(foo.__dict__, 91 {"__name__": "foo", "__doc__": "foodoc", "bar": 42, 92 "__loader__": None, "__package__": None, "__spec__": None}) 93 self.assertTrue(foo.__dict__ is d) 94 95 def test_dont_clear_dict(self): 96 # See issue 7140. 97 def f(): 98 foo = ModuleType("foo") 99 foo.bar = 4 100 return foo 101 gc_collect() 102 self.assertEqual(f().__dict__["bar"], 4) 103 104 @requires_type_collecting 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 @requires_type_collecting 270 def test_module_finalization_at_shutdown(self): 271 # Module globals and builtins should still be available during shutdown 272 rc, out, err = assert_python_ok("-c", "from test import final_a") 273 self.assertFalse(err) 274 lines = out.splitlines() 275 self.assertEqual(set(lines), { 276 b"x = a", 277 b"x = b", 278 b"final_a.x = a", 279 b"final_b.x = b", 280 b"len = len", 281 b"shutil.rmtree = rmtree"}) 282 283 def test_descriptor_errors_propagate(self): 284 class Descr: 285 def __get__(self, o, t): 286 raise RuntimeError 287 class M(ModuleType): 288 melon = Descr() 289 self.assertRaises(RuntimeError, getattr, M("mymod"), "melon") 290 291 # frozen and namespace module reprs are tested in importlib. 292 293 294if __name__ == '__main__': 295 unittest.main() 296