test_module.py 8.44 KB
Newer Older
1
# Test the module type
2
import unittest
3
import weakref
4
from test.support import gc_collect, requires_type_collecting
5
from test.support.script_helper import assert_python_ok
6 7

import sys
8 9
ModuleType = type(sys)

10 11 12 13 14 15 16 17 18
class FullLoader:
    @classmethod
    def module_repr(cls, m):
        return "<module '{}' (crafted)>".format(m.__name__)

class BareLoader:
    pass


19 20 21 22 23
class ModuleTests(unittest.TestCase):
    def test_uninitialized(self):
        # An uninitialized module has no __dict__ or __name__,
        # and __doc__ is None
        foo = ModuleType.__new__(ModuleType)
24
        self.assertTrue(foo.__dict__ is None)
25
        self.assertRaises(SystemError, dir, foo)
26 27 28 29 30 31 32
        try:
            s = foo.__name__
            self.fail("__name__ = %s" % repr(s))
        except AttributeError:
            pass
        self.assertEqual(foo.__doc__, ModuleType.__doc__)

33
    def test_uninitialized_missing_getattr(self):
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
        # Issue 8297
        # test the text in the AttributeError of an uninitialized module
        foo = ModuleType.__new__(ModuleType)
        self.assertRaisesRegex(
                AttributeError, "module has no attribute 'not_here'",
                getattr, foo, "not_here")

    def test_missing_getattr(self):
        # Issue 8297
        # test the text in the AttributeError
        foo = ModuleType("foo")
        self.assertRaisesRegex(
                AttributeError, "module 'foo' has no attribute 'not_here'",
                getattr, foo, "not_here")

49 50 51 52 53
    def test_no_docstring(self):
        # Regularly initialized module, no docstring
        foo = ModuleType("foo")
        self.assertEqual(foo.__name__, "foo")
        self.assertEqual(foo.__doc__, None)
54 55
        self.assertIs(foo.__loader__, None)
        self.assertIs(foo.__package__, None)
56
        self.assertIs(foo.__spec__, None)
57
        self.assertEqual(foo.__dict__, {"__name__": "foo", "__doc__": None,
58 59
                                        "__loader__": None, "__package__": None,
                                        "__spec__": None})
60 61 62 63 64 65 66

    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__,
67
                         {"__name__": "foo", "__doc__": "foodoc",
68 69
                          "__loader__": None, "__package__": None,
                          "__spec__": None})
70 71 72

    def test_unicode_docstring(self):
        # 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 79
                          "__loader__": None, "__package__": None,
                          "__spec__": None})
80 81 82

    def test_reinit(self):
        # Reinitialization should not replace the __dict__
83
        foo = ModuleType("foo", "foodoc\u1234")
84 85 86 87 88 89 90
        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__,
91
              {"__name__": "foo", "__doc__": "foodoc", "bar": 42,
92
               "__loader__": None, "__package__": None, "__spec__": None})
93
        self.assertTrue(foo.__dict__ is d)
94

Benjamin Peterson's avatar
Benjamin Peterson committed
95 96 97 98 99 100
    def test_dont_clear_dict(self):
        # See issue 7140.
        def f():
            foo = ModuleType("foo")
            foo.bar = 4
            return foo
101
        gc_collect()
Benjamin Peterson's avatar
Benjamin Peterson committed
102 103
        self.assertEqual(f().__dict__["bar"], 4)

104
    @requires_type_collecting
105 106 107 108 109
    def test_clear_dict_in_ref_cycle(self):
        destroyed = []
        m = ModuleType("foo")
        m.destroyed = destroyed
        s = """class A:
110 111
    def __init__(self, l):
        self.l = l
112
    def __del__(self):
113 114
        self.l.append(1)
a = A(destroyed)"""
115 116 117 118 119
        exec(s, m.__dict__)
        del m
        gc_collect()
        self.assertEqual(destroyed, [1])

120 121 122 123 124 125 126 127
    def test_weakref(self):
        m = ModuleType("foo")
        wr = weakref.ref(m)
        self.assertIs(wr(), m)
        del m
        gc_collect()
        self.assertIs(wr(), None)

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    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'>")

149 150 151 152 153
    def test_module_repr_with_loader_as_None(self):
        m = ModuleType('foo')
        assert m.__loader__ is None
        self.assertEqual(repr(m), "<module 'foo'>")

154 155 156 157 158
    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
159
        loader_repr = repr(BareLoader)
160
        self.assertEqual(
161
            repr(m), "<module '?' ({})>".format(loader_repr))
162 163 164 165 166 167 168 169 170

    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
171
        loader_repr = repr(FullLoader)
172
        self.assertEqual(
173
            repr(m), "<module '?' ({})>".format(loader_repr))
174 175 176 177 178

    def test_module_repr_with_bare_loader(self):
        m = ModuleType('foo')
        # Yes, a class not an instance.
        m.__loader__ = BareLoader
179
        module_repr = repr(BareLoader)
180
        self.assertEqual(
181
            repr(m), "<module 'foo' ({})>".format(module_repr))
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

    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)
211 212 213 214 215 216
        starts_with = "<module 'unittest' from '"
        ends_with = "__init__.py'>"
        self.assertEqual(r[:len(starts_with)], starts_with,
                         '{!r} does not start with {!r}'.format(r, starts_with))
        self.assertEqual(r[-len(ends_with):], ends_with,
                         '{!r} does not end with {!r}'.format(r, ends_with))
217

218
    @requires_type_collecting
219 220 221 222 223 224 225 226 227 228 229 230 231
    def test_module_finalization_at_shutdown(self):
        # Module globals and builtins should still be available during shutdown
        rc, out, err = assert_python_ok("-c", "from test import final_a")
        self.assertFalse(err)
        lines = out.splitlines()
        self.assertEqual(set(lines), {
            b"x = a",
            b"x = b",
            b"final_a.x = a",
            b"final_b.x = b",
            b"len = len",
            b"shutil.rmtree = rmtree"})

232
    def test_descriptor_errors_propagate(self):
233 234 235 236 237 238 239
        class Descr:
            def __get__(self, o, t):
                raise RuntimeError
        class M(ModuleType):
            melon = Descr()
        self.assertRaises(RuntimeError, getattr, M("mymod"), "melon")

240 241 242
    # frozen and namespace module reprs are tested in importlib.


243
if __name__ == '__main__':
244
    unittest.main()