1# Test the module type 2import unittest 3import weakref 4from test.support import gc_collect 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 def test_clear_dict_in_ref_cycle(self): 105 destroyed = [] 106 m = ModuleType("foo") 107 m.destroyed = destroyed 108 s = """class A: 109 def __init__(self, l): 110 self.l = l 111 def __del__(self): 112 self.l.append(1) 113a = A(destroyed)""" 114 exec(s, m.__dict__) 115 del m 116 gc_collect() 117 self.assertEqual(destroyed, [1]) 118 119 def test_weakref(self): 120 m = ModuleType("foo") 121 wr = weakref.ref(m) 122 self.assertIs(wr(), m) 123 del m 124 gc_collect() 125 self.assertIs(wr(), None) 126 127 def test_module_getattr(self): 128 import test.good_getattr as gga 129 from test.good_getattr import test 130 self.assertEqual(test, "There is test") 131 self.assertEqual(gga.x, 1) 132 self.assertEqual(gga.y, 2) 133 with self.assertRaisesRegex(AttributeError, 134 "Deprecated, use whatever instead"): 135 gga.yolo 136 self.assertEqual(gga.whatever, "There is whatever") 137 del sys.modules['test.good_getattr'] 138 139 def test_module_getattr_errors(self): 140 import test.bad_getattr as bga 141 from test import bad_getattr2 142 self.assertEqual(bga.x, 1) 143 self.assertEqual(bad_getattr2.x, 1) 144 with self.assertRaises(TypeError): 145 bga.nope 146 with self.assertRaises(TypeError): 147 bad_getattr2.nope 148 del sys.modules['test.bad_getattr'] 149 if 'test.bad_getattr2' in sys.modules: 150 del sys.modules['test.bad_getattr2'] 151 152 def test_module_dir(self): 153 import test.good_getattr as gga 154 self.assertEqual(dir(gga), ['a', 'b', 'c']) 155 del sys.modules['test.good_getattr'] 156 157 def test_module_dir_errors(self): 158 import test.bad_getattr as bga 159 from test import bad_getattr2 160 with self.assertRaises(TypeError): 161 dir(bga) 162 with self.assertRaises(TypeError): 163 dir(bad_getattr2) 164 del sys.modules['test.bad_getattr'] 165 if 'test.bad_getattr2' in sys.modules: 166 del sys.modules['test.bad_getattr2'] 167 168 def test_module_getattr_tricky(self): 169 from test import bad_getattr3 170 # these lookups should not crash 171 with self.assertRaises(AttributeError): 172 bad_getattr3.one 173 with self.assertRaises(AttributeError): 174 bad_getattr3.delgetattr 175 if 'test.bad_getattr3' in sys.modules: 176 del sys.modules['test.bad_getattr3'] 177 178 def test_module_repr_minimal(self): 179 # reprs when modules have no __file__, __name__, or __loader__ 180 m = ModuleType('foo') 181 del m.__name__ 182 self.assertEqual(repr(m), "<module '?'>") 183 184 def test_module_repr_with_name(self): 185 m = ModuleType('foo') 186 self.assertEqual(repr(m), "<module 'foo'>") 187 188 def test_module_repr_with_name_and_filename(self): 189 m = ModuleType('foo') 190 m.__file__ = '/tmp/foo.py' 191 self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") 192 193 def test_module_repr_with_filename_only(self): 194 m = ModuleType('foo') 195 del m.__name__ 196 m.__file__ = '/tmp/foo.py' 197 self.assertEqual(repr(m), "<module '?' from '/tmp/foo.py'>") 198 199 def test_module_repr_with_loader_as_None(self): 200 m = ModuleType('foo') 201 assert m.__loader__ is None 202 self.assertEqual(repr(m), "<module 'foo'>") 203 204 def test_module_repr_with_bare_loader_but_no_name(self): 205 m = ModuleType('foo') 206 del m.__name__ 207 # Yes, a class not an instance. 208 m.__loader__ = BareLoader 209 loader_repr = repr(BareLoader) 210 self.assertEqual( 211 repr(m), "<module '?' ({})>".format(loader_repr)) 212 213 def test_module_repr_with_full_loader_but_no_name(self): 214 # m.__loader__.module_repr() will fail because the module has no 215 # m.__name__. This exception will get suppressed and instead the 216 # loader's repr will be used. 217 m = ModuleType('foo') 218 del m.__name__ 219 # Yes, a class not an instance. 220 m.__loader__ = FullLoader 221 loader_repr = repr(FullLoader) 222 self.assertEqual( 223 repr(m), "<module '?' ({})>".format(loader_repr)) 224 225 def test_module_repr_with_bare_loader(self): 226 m = ModuleType('foo') 227 # Yes, a class not an instance. 228 m.__loader__ = BareLoader 229 module_repr = repr(BareLoader) 230 self.assertEqual( 231 repr(m), "<module 'foo' ({})>".format(module_repr)) 232 233 def test_module_repr_with_full_loader(self): 234 m = ModuleType('foo') 235 # Yes, a class not an instance. 236 m.__loader__ = FullLoader 237 self.assertEqual( 238 repr(m), "<module 'foo' (crafted)>") 239 240 def test_module_repr_with_bare_loader_and_filename(self): 241 # Because the loader has no module_repr(), use the file name. 242 m = ModuleType('foo') 243 # Yes, a class not an instance. 244 m.__loader__ = BareLoader 245 m.__file__ = '/tmp/foo.py' 246 self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") 247 248 def test_module_repr_with_full_loader_and_filename(self): 249 # Even though the module has an __file__, use __loader__.module_repr() 250 m = ModuleType('foo') 251 # Yes, a class not an instance. 252 m.__loader__ = FullLoader 253 m.__file__ = '/tmp/foo.py' 254 self.assertEqual(repr(m), "<module 'foo' (crafted)>") 255 256 def test_module_repr_builtin(self): 257 self.assertEqual(repr(sys), "<module 'sys' (built-in)>") 258 259 def test_module_repr_source(self): 260 r = repr(unittest) 261 starts_with = "<module 'unittest' from '" 262 ends_with = "__init__.py'>" 263 self.assertEqual(r[:len(starts_with)], starts_with, 264 '{!r} does not start with {!r}'.format(r, starts_with)) 265 self.assertEqual(r[-len(ends_with):], ends_with, 266 '{!r} does not end with {!r}'.format(r, ends_with)) 267 268 def test_module_finalization_at_shutdown(self): 269 # Module globals and builtins should still be available during shutdown 270 rc, out, err = assert_python_ok("-c", "from test import final_a") 271 self.assertFalse(err) 272 lines = out.splitlines() 273 self.assertEqual(set(lines), { 274 b"x = a", 275 b"x = b", 276 b"final_a.x = a", 277 b"final_b.x = b", 278 b"len = len", 279 b"shutil.rmtree = rmtree"}) 280 281 def test_descriptor_errors_propagate(self): 282 class Descr: 283 def __get__(self, o, t): 284 raise RuntimeError 285 class M(ModuleType): 286 melon = Descr() 287 self.assertRaises(RuntimeError, getattr, M("mymod"), "melon") 288 289 # frozen and namespace module reprs are tested in importlib. 290 291 292if __name__ == '__main__': 293 unittest.main() 294