blob: 2d415f985dc9976874773f488a2310e1d06e5f5f [file] [log] [blame]
Brett Cannon30b047d2009-02-01 02:05:11 +00001from .. import abc
Brett Cannond71bed32010-07-03 22:18:47 +00002from .. import util
Brett Cannon4ee2cda2009-02-01 03:08:31 +00003from . import util as source_util
Brett Cannon23cbd8a2009-01-18 00:24:28 +00004
Brett Cannon9ea8eda2013-11-08 14:25:37 -05005importlib = util.import_importlib('importlib')
6importlib_abc = util.import_importlib('importlib.abc')
7machinery = util.import_importlib('importlib.machinery')
8importlib_util = util.import_importlib('importlib.util')
9
Antoine Pitroudd21f682012-01-25 03:00:57 +010010import errno
Brett Cannon61b14252010-07-03 21:48:25 +000011import marshal
Brett Cannon23cbd8a2009-01-18 00:24:28 +000012import os
13import py_compile
Brett Cannon186335b2010-08-22 22:11:06 +000014import shutil
Brett Cannone52c9192009-11-07 23:55:05 +000015import stat
Brett Cannon23cbd8a2009-01-18 00:24:28 +000016import sys
Brett Cannonef888022013-06-15 18:39:21 -040017import types
Brett Cannon23cbd8a2009-01-18 00:24:28 +000018import unittest
Eric Snow1500d492014-01-06 20:49:04 -070019import warnings
Brett Cannon23cbd8a2009-01-18 00:24:28 +000020
Brett Cannon0dbb4c72013-05-31 18:56:47 -040021from test.support import make_legacy_pyc, unload
Barry Warsaw04b56842010-05-18 14:15:20 +000022
Brett Cannon23cbd8a2009-01-18 00:24:28 +000023
Brett Cannon9ea8eda2013-11-08 14:25:37 -050024class SimpleTest(abc.LoaderTests):
Brett Cannon23cbd8a2009-01-18 00:24:28 +000025
26 """Should have no issue importing a source module [basic]. And if there is
27 a syntax error, it should raise a SyntaxError [syntax error].
28
29 """
30
Eric Snowd749c7a2014-01-04 15:06:49 -070031 def setUp(self):
32 self.name = 'spam'
33 self.filepath = os.path.join('ham', self.name + '.py')
34 self.loader = self.machinery.SourceFileLoader(self.name, self.filepath)
35
Brett Cannonc0499522012-05-11 14:48:41 -040036 def test_load_module_API(self):
Brett Cannon9ea8eda2013-11-08 14:25:37 -050037 class Tester(self.abc.FileLoader):
Brett Cannon0dbb4c72013-05-31 18:56:47 -040038 def get_source(self, _): return 'attr = 42'
39 def is_package(self, _): return False
Brett Cannonc0499522012-05-11 14:48:41 -040040
Brett Cannon0dbb4c72013-05-31 18:56:47 -040041 loader = Tester('blah', 'blah.py')
42 self.addCleanup(unload, 'blah')
Eric Snow1500d492014-01-06 20:49:04 -070043 with warnings.catch_warnings():
44 warnings.simplefilter('ignore', DeprecationWarning)
45 module = loader.load_module() # Should not raise an exception.
Brett Cannonc0499522012-05-11 14:48:41 -040046
47 def test_get_filename_API(self):
48 # If fullname is not set then assume self.path is desired.
Brett Cannon9ea8eda2013-11-08 14:25:37 -050049 class Tester(self.abc.FileLoader):
Brett Cannonc0499522012-05-11 14:48:41 -040050 def get_code(self, _): pass
51 def get_source(self, _): pass
52 def is_package(self, _): pass
Barry Warsaw0efcf992012-07-31 17:52:32 -040053 def module_repr(self, _): pass
Brett Cannonc0499522012-05-11 14:48:41 -040054
55 path = 'some_path'
56 name = 'some_name'
57 loader = Tester(name, path)
58 self.assertEqual(path, loader.get_filename(name))
59 self.assertEqual(path, loader.get_filename())
60 self.assertEqual(path, loader.get_filename(None))
61 with self.assertRaises(ImportError):
62 loader.get_filename(name + 'XXX')
63
Eric Snowd749c7a2014-01-04 15:06:49 -070064 def test_equality(self):
65 other = self.machinery.SourceFileLoader(self.name, self.filepath)
66 self.assertEqual(self.loader, other)
67
68 def test_inequality(self):
69 other = self.machinery.SourceFileLoader('_' + self.name, self.filepath)
70 self.assertNotEqual(self.loader, other)
71
Brett Cannon23cbd8a2009-01-18 00:24:28 +000072 # [basic]
Brett Cannon30b047d2009-02-01 02:05:11 +000073 def test_module(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000074 with source_util.create_modules('_temp') as mapping:
Brett Cannon9ea8eda2013-11-08 14:25:37 -050075 loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
Eric Snow1500d492014-01-06 20:49:04 -070076 with warnings.catch_warnings():
77 warnings.simplefilter('ignore', DeprecationWarning)
78 module = loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -040079 self.assertIn('_temp', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000080 check = {'__name__': '_temp', '__file__': mapping['_temp'],
Brett Cannon06c9d962009-02-07 01:52:25 +000081 '__package__': ''}
Brett Cannon30b047d2009-02-01 02:05:11 +000082 for attr, value in check.items():
83 self.assertEqual(getattr(module, attr), value)
84
85 def test_package(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000086 with source_util.create_modules('_pkg.__init__') as mapping:
Brett Cannon9ea8eda2013-11-08 14:25:37 -050087 loader = self.machinery.SourceFileLoader('_pkg',
Brett Cannon61b14252010-07-03 21:48:25 +000088 mapping['_pkg.__init__'])
Eric Snow1500d492014-01-06 20:49:04 -070089 with warnings.catch_warnings():
90 warnings.simplefilter('ignore', DeprecationWarning)
91 module = loader.load_module('_pkg')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -040092 self.assertIn('_pkg', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000093 check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
94 '__path__': [os.path.dirname(mapping['_pkg.__init__'])],
95 '__package__': '_pkg'}
96 for attr, value in check.items():
97 self.assertEqual(getattr(module, attr), value)
98
99
100 def test_lacking_parent(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000101 with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500102 loader = self.machinery.SourceFileLoader('_pkg.mod',
Brett Cannon61b14252010-07-03 21:48:25 +0000103 mapping['_pkg.mod'])
Eric Snow1500d492014-01-06 20:49:04 -0700104 with warnings.catch_warnings():
105 warnings.simplefilter('ignore', DeprecationWarning)
106 module = loader.load_module('_pkg.mod')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400107 self.assertIn('_pkg.mod', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +0000108 check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
109 '__package__': '_pkg'}
110 for attr, value in check.items():
111 self.assertEqual(getattr(module, attr), value)
112
113 def fake_mtime(self, fxn):
114 """Fake mtime to always be higher than expected."""
115 return lambda name: fxn(name) + 1
116
117 def test_module_reuse(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000118 with source_util.create_modules('_temp') as mapping:
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500119 loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
Eric Snow1500d492014-01-06 20:49:04 -0700120 with warnings.catch_warnings():
121 warnings.simplefilter('ignore', DeprecationWarning)
122 module = loader.load_module('_temp')
Brett Cannon30b047d2009-02-01 02:05:11 +0000123 module_id = id(module)
124 module_dict_id = id(module.__dict__)
125 with open(mapping['_temp'], 'w') as file:
126 file.write("testing_var = 42\n")
Eric Snow1500d492014-01-06 20:49:04 -0700127 with warnings.catch_warnings():
128 warnings.simplefilter('ignore', DeprecationWarning)
129 module = loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400130 self.assertIn('testing_var', module.__dict__,
Brett Cannon30b047d2009-02-01 02:05:11 +0000131 "'testing_var' not in "
132 "{0}".format(list(module.__dict__.keys())))
133 self.assertEqual(module, sys.modules['_temp'])
134 self.assertEqual(id(module), module_id)
135 self.assertEqual(id(module.__dict__), module_dict_id)
136
137 def test_state_after_failure(self):
138 # A failed reload should leave the original module intact.
139 attributes = ('__file__', '__path__', '__package__')
140 value = '<test>'
141 name = '_temp'
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000142 with source_util.create_modules(name) as mapping:
Brett Cannonef888022013-06-15 18:39:21 -0400143 orig_module = types.ModuleType(name)
Brett Cannon30b047d2009-02-01 02:05:11 +0000144 for attr in attributes:
145 setattr(orig_module, attr, value)
146 with open(mapping[name], 'w') as file:
147 file.write('+++ bad syntax +++')
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500148 loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon2153dc02009-08-27 23:49:21 +0000149 with self.assertRaises(SyntaxError):
Brett Cannon2f8c8352013-12-06 14:25:01 -0500150 loader.exec_module(orig_module)
151 for attr in attributes:
152 self.assertEqual(getattr(orig_module, attr), value)
153 with self.assertRaises(SyntaxError):
Eric Snow1500d492014-01-06 20:49:04 -0700154 with warnings.catch_warnings():
155 warnings.simplefilter('ignore', DeprecationWarning)
156 loader.load_module(name)
Brett Cannon30b047d2009-02-01 02:05:11 +0000157 for attr in attributes:
158 self.assertEqual(getattr(orig_module, attr), value)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000159
160 # [syntax error]
161 def test_bad_syntax(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000162 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000163 with open(mapping['_temp'], 'w') as file:
164 file.write('=')
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500165 loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon2153dc02009-08-27 23:49:21 +0000166 with self.assertRaises(SyntaxError):
Eric Snow1500d492014-01-06 20:49:04 -0700167 with warnings.catch_warnings():
168 warnings.simplefilter('ignore', DeprecationWarning)
169 loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400170 self.assertNotIn('_temp', sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000171
Brett Cannond71bed32010-07-03 22:18:47 +0000172 def test_file_from_empty_string_dir(self):
173 # Loading a module found from an empty string entry on sys.path should
174 # not only work, but keep all attributes relative.
Brett Cannon186335b2010-08-22 22:11:06 +0000175 file_path = '_temp.py'
176 with open(file_path, 'w') as file:
Brett Cannond71bed32010-07-03 22:18:47 +0000177 file.write("# test file for importlib")
178 try:
179 with util.uncache('_temp'):
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500180 loader = self.machinery.SourceFileLoader('_temp', file_path)
Eric Snow1500d492014-01-06 20:49:04 -0700181 with warnings.catch_warnings():
182 warnings.simplefilter('ignore', DeprecationWarning)
183 mod = loader.load_module('_temp')
Brett Cannon186335b2010-08-22 22:11:06 +0000184 self.assertEqual(file_path, mod.__file__)
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500185 self.assertEqual(self.util.cache_from_source(file_path),
Brett Cannond71bed32010-07-03 22:18:47 +0000186 mod.__cached__)
Brett Cannond71bed32010-07-03 22:18:47 +0000187 finally:
Brett Cannon186335b2010-08-22 22:11:06 +0000188 os.unlink(file_path)
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500189 pycache = os.path.dirname(self.util.cache_from_source(file_path))
Ezio Melottic28f6fa2013-03-16 19:48:51 +0200190 if os.path.exists(pycache):
191 shutil.rmtree(pycache)
Brett Cannond71bed32010-07-03 22:18:47 +0000192
Benjamin Peterson36736702014-02-27 13:49:34 -0500193 @source_util.writes_bytecode_files
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100194 def test_timestamp_overflow(self):
195 # When a modification timestamp is larger than 2**32, it should be
196 # truncated rather than raise an OverflowError.
197 with source_util.create_modules('_temp') as mapping:
198 source = mapping['_temp']
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500199 compiled = self.util.cache_from_source(source)
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100200 with open(source, 'w') as f:
201 f.write("x = 5")
Antoine Pitroudd21f682012-01-25 03:00:57 +0100202 try:
Antoine Pitrou33d15f72012-01-25 18:01:45 +0100203 os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5))
Antoine Pitroudd21f682012-01-25 03:00:57 +0100204 except OverflowError:
205 self.skipTest("cannot set modification time to large integer")
206 except OSError as e:
207 if e.errno != getattr(errno, 'EOVERFLOW', None):
208 raise
209 self.skipTest("cannot set modification time to large integer ({})".format(e))
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500210 loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon2f8c8352013-12-06 14:25:01 -0500211 # PEP 451
212 module = types.ModuleType('_temp')
213 module.__spec__ = self.util.spec_from_loader('_temp', loader)
214 loader.exec_module(module)
215 self.assertEqual(module.x, 5)
216 self.assertTrue(os.path.exists(compiled))
217 os.unlink(compiled)
218 # PEP 302
Eric Snow1500d492014-01-06 20:49:04 -0700219 with warnings.catch_warnings():
220 warnings.simplefilter('ignore', DeprecationWarning)
221 mod = loader.load_module('_temp') # XXX
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100222 # Sanity checks.
223 self.assertEqual(mod.__cached__, compiled)
224 self.assertEqual(mod.x, 5)
225 # The pyc file was created.
Brett Cannon2f8c8352013-12-06 14:25:01 -0500226 self.assertTrue(os.path.exists(compiled))
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100227
Brett Cannonb3d6aff2013-10-25 12:33:59 -0400228 def test_unloadable(self):
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500229 loader = self.machinery.SourceFileLoader('good name', {})
Brett Cannon2f8c8352013-12-06 14:25:01 -0500230 module = types.ModuleType('bad name')
231 module.__spec__ = self.machinery.ModuleSpec('bad name', loader)
232 with self.assertRaises(ImportError):
233 loader.exec_module(module)
Brett Cannonb3d6aff2013-10-25 12:33:59 -0400234 with self.assertRaises(ImportError):
Eric Snow1500d492014-01-06 20:49:04 -0700235 with warnings.catch_warnings():
236 warnings.simplefilter('ignore', DeprecationWarning)
237 loader.load_module('bad name')
Brett Cannonb3d6aff2013-10-25 12:33:59 -0400238
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500239Frozen_SimpleTest, Source_SimpleTest = util.test_both(
240 SimpleTest, importlib=importlib, machinery=machinery, abc=importlib_abc,
241 util=importlib_util)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000242
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500243
244class BadBytecodeTest:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000245
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000246 def import_(self, file, module_name):
Brett Cannon61b14252010-07-03 21:48:25 +0000247 loader = self.loader(module_name, file)
Eric Snow1500d492014-01-06 20:49:04 -0700248 with warnings.catch_warnings():
249 warnings.simplefilter('ignore', DeprecationWarning)
250 # XXX Change to use exec_module().
251 module = loader.load_module(module_name)
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400252 self.assertIn(module_name, sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000253
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000254 def manipulate_bytecode(self, name, mapping, manipulator, *,
255 del_source=False):
256 """Manipulate the bytecode of a module by passing it into a callable
257 that returns what to use as the new bytecode."""
258 try:
259 del sys.modules['_temp']
260 except KeyError:
261 pass
262 py_compile.compile(mapping[name])
Brett Cannon61b14252010-07-03 21:48:25 +0000263 if not del_source:
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500264 bytecode_path = self.util.cache_from_source(mapping[name])
Brett Cannon61b14252010-07-03 21:48:25 +0000265 else:
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000266 os.unlink(mapping[name])
Brett Cannon61b14252010-07-03 21:48:25 +0000267 bytecode_path = make_legacy_pyc(mapping[name])
268 if manipulator:
269 with open(bytecode_path, 'rb') as file:
270 bc = file.read()
271 new_bc = manipulator(bc)
272 with open(bytecode_path, 'wb') as file:
273 if new_bc is not None:
274 file.write(new_bc)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000275 return bytecode_path
276
Brett Cannon61b14252010-07-03 21:48:25 +0000277 def _test_empty_file(self, test, *, del_source=False):
278 with source_util.create_modules('_temp') as mapping:
279 bc_path = self.manipulate_bytecode('_temp', mapping,
280 lambda bc: b'',
281 del_source=del_source)
282 test('_temp', mapping, bc_path)
283
284 @source_util.writes_bytecode_files
285 def _test_partial_magic(self, test, *, del_source=False):
286 # When their are less than 4 bytes to a .pyc, regenerate it if
287 # possible, else raise ImportError.
288 with source_util.create_modules('_temp') as mapping:
289 bc_path = self.manipulate_bytecode('_temp', mapping,
290 lambda bc: bc[:3],
291 del_source=del_source)
292 test('_temp', mapping, bc_path)
293
294 def _test_magic_only(self, test, *, del_source=False):
295 with source_util.create_modules('_temp') as mapping:
296 bc_path = self.manipulate_bytecode('_temp', mapping,
297 lambda bc: bc[:4],
298 del_source=del_source)
299 test('_temp', mapping, bc_path)
300
301 def _test_partial_timestamp(self, test, *, del_source=False):
302 with source_util.create_modules('_temp') as mapping:
303 bc_path = self.manipulate_bytecode('_temp', mapping,
304 lambda bc: bc[:7],
305 del_source=del_source)
306 test('_temp', mapping, bc_path)
307
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100308 def _test_partial_size(self, test, *, del_source=False):
309 with source_util.create_modules('_temp') as mapping:
310 bc_path = self.manipulate_bytecode('_temp', mapping,
311 lambda bc: bc[:11],
312 del_source=del_source)
313 test('_temp', mapping, bc_path)
314
Brett Cannon61b14252010-07-03 21:48:25 +0000315 def _test_no_marshal(self, *, del_source=False):
316 with source_util.create_modules('_temp') as mapping:
317 bc_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100318 lambda bc: bc[:12],
Brett Cannon61b14252010-07-03 21:48:25 +0000319 del_source=del_source)
320 file_path = mapping['_temp'] if not del_source else bc_path
321 with self.assertRaises(EOFError):
322 self.import_(file_path, '_temp')
323
324 def _test_non_code_marshal(self, *, del_source=False):
325 with source_util.create_modules('_temp') as mapping:
326 bytecode_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100327 lambda bc: bc[:12] + marshal.dumps(b'abcd'),
Brett Cannon61b14252010-07-03 21:48:25 +0000328 del_source=del_source)
329 file_path = mapping['_temp'] if not del_source else bytecode_path
Brett Cannonbbb66802012-04-12 21:09:01 -0400330 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000331 self.import_(file_path, '_temp')
Brett Cannonbbb66802012-04-12 21:09:01 -0400332 self.assertEqual(cm.exception.name, '_temp')
333 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000334
335 def _test_bad_marshal(self, *, del_source=False):
336 with source_util.create_modules('_temp') as mapping:
337 bytecode_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100338 lambda bc: bc[:12] + b'<test>',
Brett Cannon61b14252010-07-03 21:48:25 +0000339 del_source=del_source)
340 file_path = mapping['_temp'] if not del_source else bytecode_path
Vinay Sajip5bdae3b2011-07-02 16:42:47 +0100341 with self.assertRaises(EOFError):
Brett Cannon61b14252010-07-03 21:48:25 +0000342 self.import_(file_path, '_temp')
343
344 def _test_bad_magic(self, test, *, del_source=False):
345 with source_util.create_modules('_temp') as mapping:
346 bc_path = self.manipulate_bytecode('_temp', mapping,
347 lambda bc: b'\x00\x00\x00\x00' + bc[4:])
348 test('_temp', mapping, bc_path)
349
Brett Cannon2f8c8352013-12-06 14:25:01 -0500350class BadBytecodeTestPEP451(BadBytecodeTest):
Brett Cannon61b14252010-07-03 21:48:25 +0000351
Brett Cannon2f8c8352013-12-06 14:25:01 -0500352 def import_(self, file, module_name):
353 loader = self.loader(module_name, file)
354 module = types.ModuleType(module_name)
355 module.__spec__ = self.util.spec_from_loader(module_name, loader)
356 loader.exec_module(module)
357
358class BadBytecodeTestPEP302(BadBytecodeTest):
359
360 def import_(self, file, module_name):
361 loader = self.loader(module_name, file)
Eric Snow1500d492014-01-06 20:49:04 -0700362 with warnings.catch_warnings():
363 warnings.simplefilter('ignore', DeprecationWarning)
364 module = loader.load_module(module_name)
Brett Cannon2f8c8352013-12-06 14:25:01 -0500365 self.assertIn(module_name, sys.modules)
366
367
368class SourceLoaderBadBytecodeTest:
Brett Cannon61b14252010-07-03 21:48:25 +0000369
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500370 @classmethod
371 def setUpClass(cls):
372 cls.loader = cls.machinery.SourceFileLoader
Brett Cannon61b14252010-07-03 21:48:25 +0000373
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000374 @source_util.writes_bytecode_files
375 def test_empty_file(self):
376 # When a .pyc is empty, regenerate it if possible, else raise
377 # ImportError.
Brett Cannon61b14252010-07-03 21:48:25 +0000378 def test(name, mapping, bytecode_path):
379 self.import_(mapping[name], name)
380 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100381 self.assertGreater(len(file.read()), 12)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000382
Brett Cannon61b14252010-07-03 21:48:25 +0000383 self._test_empty_file(test)
384
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000385 def test_partial_magic(self):
Brett Cannon61b14252010-07-03 21:48:25 +0000386 def test(name, mapping, bytecode_path):
387 self.import_(mapping[name], name)
388 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100389 self.assertGreater(len(file.read()), 12)
Brett Cannon61b14252010-07-03 21:48:25 +0000390
391 self._test_partial_magic(test)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000392
393 @source_util.writes_bytecode_files
394 def test_magic_only(self):
395 # When there is only the magic number, regenerate the .pyc if possible,
396 # else raise EOFError.
Brett Cannon61b14252010-07-03 21:48:25 +0000397 def test(name, mapping, bytecode_path):
398 self.import_(mapping[name], name)
399 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100400 self.assertGreater(len(file.read()), 12)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000401
Antoine Pitrou7c9907e2011-12-30 21:25:15 +0100402 self._test_magic_only(test)
403
Brett Cannon1262e7c2009-05-11 01:47:11 +0000404 @source_util.writes_bytecode_files
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000405 def test_bad_magic(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000406 # When the magic number is different, the bytecode should be
407 # regenerated.
Brett Cannon61b14252010-07-03 21:48:25 +0000408 def test(name, mapping, bytecode_path):
409 self.import_(mapping[name], name)
410 with open(bytecode_path, 'rb') as bytecode_file:
Brett Cannonef888022013-06-15 18:39:21 -0400411 self.assertEqual(bytecode_file.read(4),
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500412 self.util.MAGIC_NUMBER)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000413
Brett Cannon61b14252010-07-03 21:48:25 +0000414 self._test_bad_magic(test)
415
416 @source_util.writes_bytecode_files
417 def test_partial_timestamp(self):
418 # When the timestamp is partial, regenerate the .pyc, else
419 # raise EOFError.
420 def test(name, mapping, bc_path):
421 self.import_(mapping[name], name)
422 with open(bc_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100423 self.assertGreater(len(file.read()), 12)
Brett Cannon61b14252010-07-03 21:48:25 +0000424
Antoine Pitrou7c9907e2011-12-30 21:25:15 +0100425 self._test_partial_timestamp(test)
426
Brett Cannon61b14252010-07-03 21:48:25 +0000427 @source_util.writes_bytecode_files
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100428 def test_partial_size(self):
429 # When the size is partial, regenerate the .pyc, else
430 # raise EOFError.
431 def test(name, mapping, bc_path):
432 self.import_(mapping[name], name)
433 with open(bc_path, 'rb') as file:
434 self.assertGreater(len(file.read()), 12)
435
436 self._test_partial_size(test)
437
438 @source_util.writes_bytecode_files
Brett Cannon61b14252010-07-03 21:48:25 +0000439 def test_no_marshal(self):
440 # When there is only the magic number and timestamp, raise EOFError.
441 self._test_no_marshal()
442
443 @source_util.writes_bytecode_files
444 def test_non_code_marshal(self):
445 self._test_non_code_marshal()
446 # XXX ImportError when sourceless
447
448 # [bad marshal]
449 @source_util.writes_bytecode_files
450 def test_bad_marshal(self):
451 # Bad marshal data should raise a ValueError.
452 self._test_bad_marshal()
453
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000454 # [bad timestamp]
Brett Cannon1262e7c2009-05-11 01:47:11 +0000455 @source_util.writes_bytecode_files
Brett Cannon61b14252010-07-03 21:48:25 +0000456 def test_old_timestamp(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000457 # When the timestamp is older than the source, bytecode should be
458 # regenerated.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000459 zeros = b'\x00\x00\x00\x00'
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000460 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000461 py_compile.compile(mapping['_temp'])
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500462 bytecode_path = self.util.cache_from_source(mapping['_temp'])
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000463 with open(bytecode_path, 'r+b') as bytecode_file:
464 bytecode_file.seek(4)
465 bytecode_file.write(zeros)
466 self.import_(mapping['_temp'], '_temp')
467 source_mtime = os.path.getmtime(mapping['_temp'])
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500468 source_timestamp = self.importlib._w_long(source_mtime)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000469 with open(bytecode_path, 'rb') as bytecode_file:
470 bytecode_file.seek(4)
471 self.assertEqual(bytecode_file.read(4), source_timestamp)
472
Brett Cannone52c9192009-11-07 23:55:05 +0000473 # [bytecode read-only]
474 @source_util.writes_bytecode_files
475 def test_read_only_bytecode(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000476 # When bytecode is read-only but should be rewritten, fail silently.
Brett Cannone52c9192009-11-07 23:55:05 +0000477 with source_util.create_modules('_temp') as mapping:
478 # Create bytecode that will need to be re-created.
479 py_compile.compile(mapping['_temp'])
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500480 bytecode_path = self.util.cache_from_source(mapping['_temp'])
Brett Cannone52c9192009-11-07 23:55:05 +0000481 with open(bytecode_path, 'r+b') as bytecode_file:
482 bytecode_file.seek(0)
483 bytecode_file.write(b'\x00\x00\x00\x00')
484 # Make the bytecode read-only.
485 os.chmod(bytecode_path,
486 stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
487 try:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200488 # Should not raise OSError!
Brett Cannone52c9192009-11-07 23:55:05 +0000489 self.import_(mapping['_temp'], '_temp')
490 finally:
491 # Make writable for eventual clean-up.
492 os.chmod(bytecode_path, stat.S_IWUSR)
493
Brett Cannon2f8c8352013-12-06 14:25:01 -0500494class SourceLoaderBadBytecodeTestPEP451(
495 SourceLoaderBadBytecodeTest, BadBytecodeTestPEP451):
496 pass
497
498Frozen_SourceBadBytecodePEP451, Source_SourceBadBytecodePEP451 = util.test_both(
499 SourceLoaderBadBytecodeTestPEP451, importlib=importlib, machinery=machinery,
500 abc=importlib_abc, util=importlib_util)
501
502class SourceLoaderBadBytecodeTestPEP302(
503 SourceLoaderBadBytecodeTest, BadBytecodeTestPEP302):
504 pass
505
506Frozen_SourceBadBytecodePEP302, Source_SourceBadBytecodePEP302 = util.test_both(
507 SourceLoaderBadBytecodeTestPEP302, importlib=importlib, machinery=machinery,
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500508 abc=importlib_abc, util=importlib_util)
509
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000510
Brett Cannon2f8c8352013-12-06 14:25:01 -0500511class SourcelessLoaderBadBytecodeTest:
Brett Cannon61b14252010-07-03 21:48:25 +0000512
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500513 @classmethod
514 def setUpClass(cls):
515 cls.loader = cls.machinery.SourcelessFileLoader
Brett Cannon61b14252010-07-03 21:48:25 +0000516
517 def test_empty_file(self):
518 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400519 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000520 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400521 self.assertEqual(cm.exception.name, name)
522 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000523
524 self._test_empty_file(test, del_source=True)
525
526 def test_partial_magic(self):
527 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400528 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000529 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400530 self.assertEqual(cm.exception.name, name)
531 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000532 self._test_partial_magic(test, del_source=True)
533
534 def test_magic_only(self):
535 def test(name, mapping, bytecode_path):
536 with self.assertRaises(EOFError):
537 self.import_(bytecode_path, name)
538
539 self._test_magic_only(test, del_source=True)
540
541 def test_bad_magic(self):
542 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400543 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000544 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400545 self.assertEqual(cm.exception.name, name)
546 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000547
548 self._test_bad_magic(test, del_source=True)
549
550 def test_partial_timestamp(self):
551 def test(name, mapping, bytecode_path):
552 with self.assertRaises(EOFError):
553 self.import_(bytecode_path, name)
554
555 self._test_partial_timestamp(test, del_source=True)
556
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100557 def test_partial_size(self):
558 def test(name, mapping, bytecode_path):
559 with self.assertRaises(EOFError):
560 self.import_(bytecode_path, name)
561
562 self._test_partial_size(test, del_source=True)
563
Brett Cannon61b14252010-07-03 21:48:25 +0000564 def test_no_marshal(self):
565 self._test_no_marshal(del_source=True)
566
567 def test_non_code_marshal(self):
568 self._test_non_code_marshal(del_source=True)
569
Brett Cannon2f8c8352013-12-06 14:25:01 -0500570class SourcelessLoaderBadBytecodeTestPEP451(SourcelessLoaderBadBytecodeTest,
571 BadBytecodeTestPEP451):
572 pass
573
574Frozen_SourcelessBadBytecodePEP451, Source_SourcelessBadBytecodePEP451 = util.test_both(
575 SourcelessLoaderBadBytecodeTestPEP451, importlib=importlib,
576 machinery=machinery, abc=importlib_abc, util=importlib_util)
577
578class SourcelessLoaderBadBytecodeTestPEP302(SourcelessLoaderBadBytecodeTest,
579 BadBytecodeTestPEP302):
580 pass
581
582Frozen_SourcelessBadBytecodePEP302, Source_SourcelessBadBytecodePEP302 = util.test_both(
583 SourcelessLoaderBadBytecodeTestPEP302, importlib=importlib,
Brett Cannon9ea8eda2013-11-08 14:25:37 -0500584 machinery=machinery, abc=importlib_abc, util=importlib_util)
Brett Cannon61b14252010-07-03 21:48:25 +0000585
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000586
587if __name__ == '__main__':
Brett Cannon0dbb4c72013-05-31 18:56:47 -0400588 unittest.main()