blob: b18750c2a38939f570012dcb488e8ba9faf6c4b3 [file] [log] [blame]
Brett Cannon23cbd8a2009-01-18 00:24:28 +00001import importlib
Brett Cannonf87e04d2009-03-12 22:47:53 +00002from importlib import _bootstrap
Brett Cannon30b047d2009-02-01 02:05:11 +00003from .. import abc
Brett Cannon4ee2cda2009-02-01 03:08:31 +00004from . import util as source_util
Brett Cannon23cbd8a2009-01-18 00:24:28 +00005
6import imp
7import os
8import py_compile
9import sys
10import unittest
11
12
13class SimpleTest(unittest.TestCase):
14
15 """Should have no issue importing a source module [basic]. And if there is
16 a syntax error, it should raise a SyntaxError [syntax error].
17
18 """
19
20 # [basic]
Brett Cannon30b047d2009-02-01 02:05:11 +000021 def test_module(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000022 with source_util.create_modules('_temp') as mapping:
Brett Cannonf87e04d2009-03-12 22:47:53 +000023 loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'],
24 False)
Brett Cannon30b047d2009-02-01 02:05:11 +000025 module = loader.load_module('_temp')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000026 self.assertTrue('_temp' in sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000027 check = {'__name__': '_temp', '__file__': mapping['_temp'],
Brett Cannon06c9d962009-02-07 01:52:25 +000028 '__package__': ''}
Brett Cannon30b047d2009-02-01 02:05:11 +000029 for attr, value in check.items():
30 self.assertEqual(getattr(module, attr), value)
31
32 def test_package(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000033 with source_util.create_modules('_pkg.__init__') as mapping:
Brett Cannonf87e04d2009-03-12 22:47:53 +000034 loader = _bootstrap._PyPycFileLoader('_pkg',
35 mapping['_pkg.__init__'],
36 True)
Brett Cannon30b047d2009-02-01 02:05:11 +000037 module = loader.load_module('_pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000038 self.assertTrue('_pkg' in sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000039 check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
40 '__path__': [os.path.dirname(mapping['_pkg.__init__'])],
41 '__package__': '_pkg'}
42 for attr, value in check.items():
43 self.assertEqual(getattr(module, attr), value)
44
45
46 def test_lacking_parent(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000047 with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
Brett Cannonf87e04d2009-03-12 22:47:53 +000048 loader = _bootstrap._PyPycFileLoader('_pkg.mod',
49 mapping['_pkg.mod'], False)
Brett Cannon30b047d2009-02-01 02:05:11 +000050 module = loader.load_module('_pkg.mod')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000051 self.assertTrue('_pkg.mod' in sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000052 check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
53 '__package__': '_pkg'}
54 for attr, value in check.items():
55 self.assertEqual(getattr(module, attr), value)
56
57 def fake_mtime(self, fxn):
58 """Fake mtime to always be higher than expected."""
59 return lambda name: fxn(name) + 1
60
61 def test_module_reuse(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000062 with source_util.create_modules('_temp') as mapping:
Brett Cannonf87e04d2009-03-12 22:47:53 +000063 loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'],
64 False)
Brett Cannon30b047d2009-02-01 02:05:11 +000065 module = loader.load_module('_temp')
66 module_id = id(module)
67 module_dict_id = id(module.__dict__)
68 with open(mapping['_temp'], 'w') as file:
69 file.write("testing_var = 42\n")
70 # For filesystems where the mtime is only to a second granularity,
71 # everything that has happened above can be too fast;
72 # force an mtime on the source that is guaranteed to be different
73 # than the original mtime.
74 loader.source_mtime = self.fake_mtime(loader.source_mtime)
75 module = loader.load_module('_temp')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000076 self.assertTrue('testing_var' in module.__dict__,
Brett Cannon30b047d2009-02-01 02:05:11 +000077 "'testing_var' not in "
78 "{0}".format(list(module.__dict__.keys())))
79 self.assertEqual(module, sys.modules['_temp'])
80 self.assertEqual(id(module), module_id)
81 self.assertEqual(id(module.__dict__), module_dict_id)
82
83 def test_state_after_failure(self):
84 # A failed reload should leave the original module intact.
85 attributes = ('__file__', '__path__', '__package__')
86 value = '<test>'
87 name = '_temp'
Brett Cannon4ee2cda2009-02-01 03:08:31 +000088 with source_util.create_modules(name) as mapping:
Brett Cannon30b047d2009-02-01 02:05:11 +000089 orig_module = imp.new_module(name)
90 for attr in attributes:
91 setattr(orig_module, attr, value)
92 with open(mapping[name], 'w') as file:
93 file.write('+++ bad syntax +++')
Brett Cannonf87e04d2009-03-12 22:47:53 +000094 loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'],
95 False)
Brett Cannon2153dc02009-08-27 23:49:21 +000096 with self.assertRaises(SyntaxError):
97 loader.load_module(name)
Brett Cannon30b047d2009-02-01 02:05:11 +000098 for attr in attributes:
99 self.assertEqual(getattr(orig_module, attr), value)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000100
101 # [syntax error]
102 def test_bad_syntax(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000103 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000104 with open(mapping['_temp'], 'w') as file:
105 file.write('=')
Brett Cannonf87e04d2009-03-12 22:47:53 +0000106 loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'],
107 False)
Brett Cannon2153dc02009-08-27 23:49:21 +0000108 with self.assertRaises(SyntaxError):
109 loader.load_module('_temp')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000110 self.assertTrue('_temp' not in sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000111
112
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000113class BadBytecodeTest(unittest.TestCase):
114
115 """But there are several things about the bytecode which might lead to the
116 source being preferred. If the magic number differs from what the
117 interpreter uses, then the source is used with the bytecode regenerated.
118 If the timestamp is older than the modification time for the source then
119 the bytecode is not used [bad timestamp].
120
121 But if the marshal data is bad, even if the magic number and timestamp
122 work, a ValueError is raised and the source is not used [bad marshal].
123
124 """
125
126 def import_(self, file, module_name):
Brett Cannonf87e04d2009-03-12 22:47:53 +0000127 loader = _bootstrap._PyPycFileLoader(module_name, file, False)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000128 module = loader.load_module(module_name)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000129 self.assertTrue(module_name in sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000130
131 # [bad magic]
Brett Cannon1262e7c2009-05-11 01:47:11 +0000132 @source_util.writes_bytecode_files
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000133 def test_bad_magic(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000134 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000135 py_compile.compile(mapping['_temp'])
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000136 bytecode_path = source_util.bytecode_path(mapping['_temp'])
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000137 with open(bytecode_path, 'r+b') as bytecode_file:
138 bytecode_file.seek(0)
139 bytecode_file.write(b'\x00\x00\x00\x00')
140 self.import_(mapping['_temp'], '_temp')
141 with open(bytecode_path, 'rb') as bytecode_file:
142 self.assertEqual(bytecode_file.read(4), imp.get_magic())
143
144 # [bad timestamp]
Brett Cannon1262e7c2009-05-11 01:47:11 +0000145 @source_util.writes_bytecode_files
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000146 def test_bad_bytecode(self):
147 zeros = b'\x00\x00\x00\x00'
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000148 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000149 py_compile.compile(mapping['_temp'])
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000150 bytecode_path = source_util.bytecode_path(mapping['_temp'])
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000151 with open(bytecode_path, 'r+b') as bytecode_file:
152 bytecode_file.seek(4)
153 bytecode_file.write(zeros)
154 self.import_(mapping['_temp'], '_temp')
155 source_mtime = os.path.getmtime(mapping['_temp'])
156 source_timestamp = importlib._w_long(source_mtime)
157 with open(bytecode_path, 'rb') as bytecode_file:
158 bytecode_file.seek(4)
159 self.assertEqual(bytecode_file.read(4), source_timestamp)
160
161 # [bad marshal]
162 def test_bad_marshal(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000163 with source_util.create_modules('_temp') as mapping:
164 bytecode_path = source_util.bytecode_path(mapping['_temp'])
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000165 source_mtime = os.path.getmtime(mapping['_temp'])
166 source_timestamp = importlib._w_long(source_mtime)
167 with open(bytecode_path, 'wb') as bytecode_file:
168 bytecode_file.write(imp.get_magic())
169 bytecode_file.write(source_timestamp)
170 bytecode_file.write(b'AAAA')
Brett Cannon2153dc02009-08-27 23:49:21 +0000171 with self.assertRaises(ValueError):
172 self.import_(mapping['_temp'], '_temp')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000173 self.assertTrue('_temp' not in sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000174
175
176def test_main():
177 from test.support import run_unittest
178 run_unittest(SimpleTest, DontWriteBytecodeTest, BadDataTest,
179 SourceBytecodeInteraction, BadBytecodeTest)
180
181
182if __name__ == '__main__':
183 test_main()