| # Test the module type |
| import unittest |
| from test.support import run_unittest, gc_collect |
| |
| import sys |
| ModuleType = type(sys) |
| |
| class FullLoader: |
| @classmethod |
| def module_repr(cls, m): |
| return "<module '{}' (crafted)>".format(m.__name__) |
| |
| class BareLoader: |
| pass |
| |
| |
| class ModuleTests(unittest.TestCase): |
| def test_uninitialized(self): |
| # An uninitialized module has no __dict__ or __name__, |
| # and __doc__ is None |
| foo = ModuleType.__new__(ModuleType) |
| self.assertTrue(foo.__dict__ is None) |
| self.assertRaises(SystemError, dir, foo) |
| try: |
| s = foo.__name__ |
| self.fail("__name__ = %s" % repr(s)) |
| except AttributeError: |
| pass |
| self.assertEqual(foo.__doc__, ModuleType.__doc__) |
| |
| def test_no_docstring(self): |
| # Regularly initialized module, no docstring |
| foo = ModuleType("foo") |
| self.assertEqual(foo.__name__, "foo") |
| self.assertEqual(foo.__doc__, None) |
| self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None}) |
| |
| def test_ascii_docstring(self): |
| # ASCII docstring |
| foo = ModuleType("foo", "foodoc") |
| self.assertEqual(foo.__name__, "foo") |
| self.assertEqual(foo.__doc__, "foodoc") |
| self.assertEqual(foo.__dict__, |
| {"__name__": "foo", "__doc__": "foodoc"}) |
| |
| def test_unicode_docstring(self): |
| # Unicode docstring |
| foo = ModuleType("foo", "foodoc\u1234") |
| self.assertEqual(foo.__name__, "foo") |
| self.assertEqual(foo.__doc__, "foodoc\u1234") |
| self.assertEqual(foo.__dict__, |
| {"__name__": "foo", "__doc__": "foodoc\u1234"}) |
| |
| def test_reinit(self): |
| # Reinitialization should not replace the __dict__ |
| foo = ModuleType("foo", "foodoc\u1234") |
| foo.bar = 42 |
| d = foo.__dict__ |
| foo.__init__("foo", "foodoc") |
| self.assertEqual(foo.__name__, "foo") |
| self.assertEqual(foo.__doc__, "foodoc") |
| self.assertEqual(foo.bar, 42) |
| self.assertEqual(foo.__dict__, |
| {"__name__": "foo", "__doc__": "foodoc", "bar": 42}) |
| self.assertTrue(foo.__dict__ is d) |
| |
| @unittest.expectedFailure |
| def test_dont_clear_dict(self): |
| # See issue 7140. |
| def f(): |
| foo = ModuleType("foo") |
| foo.bar = 4 |
| return foo |
| gc_collect() |
| self.assertEqual(f().__dict__["bar"], 4) |
| |
| def test_clear_dict_in_ref_cycle(self): |
| destroyed = [] |
| m = ModuleType("foo") |
| m.destroyed = destroyed |
| s = """class A: |
| def __init__(self, l): |
| self.l = l |
| def __del__(self): |
| self.l.append(1) |
| a = A(destroyed)""" |
| exec(s, m.__dict__) |
| del m |
| gc_collect() |
| self.assertEqual(destroyed, [1]) |
| |
| def test_module_repr_minimal(self): |
| # reprs when modules have no __file__, __name__, or __loader__ |
| m = ModuleType('foo') |
| del m.__name__ |
| self.assertEqual(repr(m), "<module '?'>") |
| |
| def test_module_repr_with_name(self): |
| m = ModuleType('foo') |
| self.assertEqual(repr(m), "<module 'foo'>") |
| |
| def test_module_repr_with_name_and_filename(self): |
| m = ModuleType('foo') |
| m.__file__ = '/tmp/foo.py' |
| self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") |
| |
| def test_module_repr_with_filename_only(self): |
| m = ModuleType('foo') |
| del m.__name__ |
| m.__file__ = '/tmp/foo.py' |
| self.assertEqual(repr(m), "<module '?' from '/tmp/foo.py'>") |
| |
| def test_module_repr_with_bare_loader_but_no_name(self): |
| m = ModuleType('foo') |
| del m.__name__ |
| # Yes, a class not an instance. |
| m.__loader__ = BareLoader |
| self.assertEqual( |
| repr(m), "<module '?' (<class 'test.test_module.BareLoader'>)>") |
| |
| def test_module_repr_with_full_loader_but_no_name(self): |
| # m.__loader__.module_repr() will fail because the module has no |
| # m.__name__. This exception will get suppressed and instead the |
| # loader's repr will be used. |
| m = ModuleType('foo') |
| del m.__name__ |
| # Yes, a class not an instance. |
| m.__loader__ = FullLoader |
| self.assertEqual( |
| repr(m), "<module '?' (<class 'test.test_module.FullLoader'>)>") |
| |
| def test_module_repr_with_bare_loader(self): |
| m = ModuleType('foo') |
| # Yes, a class not an instance. |
| m.__loader__ = BareLoader |
| self.assertEqual( |
| repr(m), "<module 'foo' (<class 'test.test_module.BareLoader'>)>") |
| |
| def test_module_repr_with_full_loader(self): |
| m = ModuleType('foo') |
| # Yes, a class not an instance. |
| m.__loader__ = FullLoader |
| self.assertEqual( |
| repr(m), "<module 'foo' (crafted)>") |
| |
| def test_module_repr_with_bare_loader_and_filename(self): |
| # Because the loader has no module_repr(), use the file name. |
| m = ModuleType('foo') |
| # Yes, a class not an instance. |
| m.__loader__ = BareLoader |
| m.__file__ = '/tmp/foo.py' |
| self.assertEqual(repr(m), "<module 'foo' from '/tmp/foo.py'>") |
| |
| def test_module_repr_with_full_loader_and_filename(self): |
| # Even though the module has an __file__, use __loader__.module_repr() |
| m = ModuleType('foo') |
| # Yes, a class not an instance. |
| m.__loader__ = FullLoader |
| m.__file__ = '/tmp/foo.py' |
| self.assertEqual(repr(m), "<module 'foo' (crafted)>") |
| |
| def test_module_repr_builtin(self): |
| self.assertEqual(repr(sys), "<module 'sys' (built-in)>") |
| |
| def test_module_repr_source(self): |
| r = repr(unittest) |
| self.assertEqual(r[:25], "<module 'unittest' from '") |
| self.assertEqual(r[-13:], "__init__.py'>") |
| |
| # frozen and namespace module reprs are tested in importlib. |
| |
| |
| def test_main(): |
| run_unittest(ModuleTests) |
| |
| |
| if __name__ == '__main__': |
| test_main() |