blob: 90f9d30129e33b7d4fb8279d05e1050b1b721fd6 [file] [log] [blame]
Brett Cannon45a5e3a2012-07-20 14:48:53 -04001from importlib import machinery
Brett Cannon23cbd8a2009-01-18 00:24:28 +00002import importlib
Brett Cannonc0499522012-05-11 14:48:41 -04003import importlib.abc
Brett Cannon30b047d2009-02-01 02:05:11 +00004from .. import abc
Brett Cannond71bed32010-07-03 22:18:47 +00005from .. import util
Brett Cannon4ee2cda2009-02-01 03:08:31 +00006from . import util as source_util
Brett Cannon23cbd8a2009-01-18 00:24:28 +00007
Antoine Pitroudd21f682012-01-25 03:00:57 +01008import errno
Brett Cannon23cbd8a2009-01-18 00:24:28 +00009import imp
Brett Cannon61b14252010-07-03 21:48:25 +000010import marshal
Brett Cannon23cbd8a2009-01-18 00:24:28 +000011import os
12import py_compile
Brett Cannon186335b2010-08-22 22:11:06 +000013import shutil
Brett Cannone52c9192009-11-07 23:55:05 +000014import stat
Brett Cannon23cbd8a2009-01-18 00:24:28 +000015import sys
16import unittest
17
Barry Warsaw04b56842010-05-18 14:15:20 +000018from test.support import make_legacy_pyc
19
Brett Cannon23cbd8a2009-01-18 00:24:28 +000020
21class SimpleTest(unittest.TestCase):
22
23 """Should have no issue importing a source module [basic]. And if there is
24 a syntax error, it should raise a SyntaxError [syntax error].
25
26 """
27
Brett Cannonc0499522012-05-11 14:48:41 -040028 def test_load_module_API(self):
29 # If fullname is not specified that assume self.name is desired.
30 class TesterMixin(importlib.abc.Loader):
31 def load_module(self, fullname): return fullname
Barry Warsaw0efcf992012-07-31 17:52:32 -040032 def module_repr(self, module): return '<module>'
Brett Cannonc0499522012-05-11 14:48:41 -040033
34 class Tester(importlib.abc.FileLoader, TesterMixin):
35 def get_code(self, _): pass
36 def get_source(self, _): pass
37 def is_package(self, _): pass
38
39 name = 'mod_name'
40 loader = Tester(name, 'some_path')
41 self.assertEqual(name, loader.load_module())
42 self.assertEqual(name, loader.load_module(None))
43 self.assertEqual(name, loader.load_module(name))
44 with self.assertRaises(ImportError):
45 loader.load_module(loader.name + 'XXX')
46
47 def test_get_filename_API(self):
48 # If fullname is not set then assume self.path is desired.
49 class Tester(importlib.abc.FileLoader):
50 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
Brett Cannon23cbd8a2009-01-18 00:24:28 +000064 # [basic]
Brett Cannon30b047d2009-02-01 02:05:11 +000065 def test_module(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000066 with source_util.create_modules('_temp') as mapping:
Brett Cannon45a5e3a2012-07-20 14:48:53 -040067 loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon30b047d2009-02-01 02:05:11 +000068 module = loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -040069 self.assertIn('_temp', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000070 check = {'__name__': '_temp', '__file__': mapping['_temp'],
Brett Cannon06c9d962009-02-07 01:52:25 +000071 '__package__': ''}
Brett Cannon30b047d2009-02-01 02:05:11 +000072 for attr, value in check.items():
73 self.assertEqual(getattr(module, attr), value)
74
75 def test_package(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000076 with source_util.create_modules('_pkg.__init__') as mapping:
Brett Cannon45a5e3a2012-07-20 14:48:53 -040077 loader = machinery.SourceFileLoader('_pkg',
Brett Cannon61b14252010-07-03 21:48:25 +000078 mapping['_pkg.__init__'])
Brett Cannon30b047d2009-02-01 02:05:11 +000079 module = loader.load_module('_pkg')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -040080 self.assertIn('_pkg', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000081 check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
82 '__path__': [os.path.dirname(mapping['_pkg.__init__'])],
83 '__package__': '_pkg'}
84 for attr, value in check.items():
85 self.assertEqual(getattr(module, attr), value)
86
87
88 def test_lacking_parent(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +000089 with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
Brett Cannon45a5e3a2012-07-20 14:48:53 -040090 loader = machinery.SourceFileLoader('_pkg.mod',
Brett Cannon61b14252010-07-03 21:48:25 +000091 mapping['_pkg.mod'])
Brett Cannon30b047d2009-02-01 02:05:11 +000092 module = loader.load_module('_pkg.mod')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -040093 self.assertIn('_pkg.mod', sys.modules)
Brett Cannon30b047d2009-02-01 02:05:11 +000094 check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
95 '__package__': '_pkg'}
96 for attr, value in check.items():
97 self.assertEqual(getattr(module, attr), value)
98
99 def fake_mtime(self, fxn):
100 """Fake mtime to always be higher than expected."""
101 return lambda name: fxn(name) + 1
102
103 def test_module_reuse(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000104 with source_util.create_modules('_temp') as mapping:
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400105 loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon30b047d2009-02-01 02:05:11 +0000106 module = loader.load_module('_temp')
107 module_id = id(module)
108 module_dict_id = id(module.__dict__)
109 with open(mapping['_temp'], 'w') as file:
110 file.write("testing_var = 42\n")
Brett Cannon30b047d2009-02-01 02:05:11 +0000111 module = loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400112 self.assertIn('testing_var', module.__dict__,
Brett Cannon30b047d2009-02-01 02:05:11 +0000113 "'testing_var' not in "
114 "{0}".format(list(module.__dict__.keys())))
115 self.assertEqual(module, sys.modules['_temp'])
116 self.assertEqual(id(module), module_id)
117 self.assertEqual(id(module.__dict__), module_dict_id)
118
119 def test_state_after_failure(self):
120 # A failed reload should leave the original module intact.
121 attributes = ('__file__', '__path__', '__package__')
122 value = '<test>'
123 name = '_temp'
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000124 with source_util.create_modules(name) as mapping:
Brett Cannon30b047d2009-02-01 02:05:11 +0000125 orig_module = imp.new_module(name)
126 for attr in attributes:
127 setattr(orig_module, attr, value)
128 with open(mapping[name], 'w') as file:
129 file.write('+++ bad syntax +++')
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400130 loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon2153dc02009-08-27 23:49:21 +0000131 with self.assertRaises(SyntaxError):
132 loader.load_module(name)
Brett Cannon30b047d2009-02-01 02:05:11 +0000133 for attr in attributes:
134 self.assertEqual(getattr(orig_module, attr), value)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000135
136 # [syntax error]
137 def test_bad_syntax(self):
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000138 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000139 with open(mapping['_temp'], 'w') as file:
140 file.write('=')
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400141 loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
Brett Cannon2153dc02009-08-27 23:49:21 +0000142 with self.assertRaises(SyntaxError):
143 loader.load_module('_temp')
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400144 self.assertNotIn('_temp', sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000145
Brett Cannond71bed32010-07-03 22:18:47 +0000146 def test_file_from_empty_string_dir(self):
147 # Loading a module found from an empty string entry on sys.path should
148 # not only work, but keep all attributes relative.
Brett Cannon186335b2010-08-22 22:11:06 +0000149 file_path = '_temp.py'
150 with open(file_path, 'w') as file:
Brett Cannond71bed32010-07-03 22:18:47 +0000151 file.write("# test file for importlib")
152 try:
153 with util.uncache('_temp'):
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400154 loader = machinery.SourceFileLoader('_temp', file_path)
Brett Cannond71bed32010-07-03 22:18:47 +0000155 mod = loader.load_module('_temp')
Brett Cannon186335b2010-08-22 22:11:06 +0000156 self.assertEqual(file_path, mod.__file__)
157 self.assertEqual(imp.cache_from_source(file_path),
Brett Cannond71bed32010-07-03 22:18:47 +0000158 mod.__cached__)
Brett Cannond71bed32010-07-03 22:18:47 +0000159 finally:
Brett Cannon186335b2010-08-22 22:11:06 +0000160 os.unlink(file_path)
161 pycache = os.path.dirname(imp.cache_from_source(file_path))
162 shutil.rmtree(pycache)
Brett Cannond71bed32010-07-03 22:18:47 +0000163
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100164 def test_timestamp_overflow(self):
165 # When a modification timestamp is larger than 2**32, it should be
166 # truncated rather than raise an OverflowError.
167 with source_util.create_modules('_temp') as mapping:
168 source = mapping['_temp']
169 compiled = imp.cache_from_source(source)
170 with open(source, 'w') as f:
171 f.write("x = 5")
Antoine Pitroudd21f682012-01-25 03:00:57 +0100172 try:
Antoine Pitrou33d15f72012-01-25 18:01:45 +0100173 os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5))
Antoine Pitroudd21f682012-01-25 03:00:57 +0100174 except OverflowError:
175 self.skipTest("cannot set modification time to large integer")
176 except OSError as e:
177 if e.errno != getattr(errno, 'EOVERFLOW', None):
178 raise
179 self.skipTest("cannot set modification time to large integer ({})".format(e))
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400180 loader = machinery.SourceFileLoader('_temp', mapping['_temp'])
Antoine Pitrou2be60af2012-01-24 17:44:06 +0100181 mod = loader.load_module('_temp')
182 # Sanity checks.
183 self.assertEqual(mod.__cached__, compiled)
184 self.assertEqual(mod.x, 5)
185 # The pyc file was created.
186 os.stat(compiled)
187
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000188
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000189class BadBytecodeTest(unittest.TestCase):
190
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000191 def import_(self, file, module_name):
Brett Cannon61b14252010-07-03 21:48:25 +0000192 loader = self.loader(module_name, file)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000193 module = loader.load_module(module_name)
Eric V. Smithfaae3ad2012-06-27 15:26:26 -0400194 self.assertIn(module_name, sys.modules)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000195
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000196 def manipulate_bytecode(self, name, mapping, manipulator, *,
197 del_source=False):
198 """Manipulate the bytecode of a module by passing it into a callable
199 that returns what to use as the new bytecode."""
200 try:
201 del sys.modules['_temp']
202 except KeyError:
203 pass
204 py_compile.compile(mapping[name])
Brett Cannon61b14252010-07-03 21:48:25 +0000205 if not del_source:
206 bytecode_path = imp.cache_from_source(mapping[name])
207 else:
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000208 os.unlink(mapping[name])
Brett Cannon61b14252010-07-03 21:48:25 +0000209 bytecode_path = make_legacy_pyc(mapping[name])
210 if manipulator:
211 with open(bytecode_path, 'rb') as file:
212 bc = file.read()
213 new_bc = manipulator(bc)
214 with open(bytecode_path, 'wb') as file:
215 if new_bc is not None:
216 file.write(new_bc)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000217 return bytecode_path
218
Brett Cannon61b14252010-07-03 21:48:25 +0000219 def _test_empty_file(self, test, *, del_source=False):
220 with source_util.create_modules('_temp') as mapping:
221 bc_path = self.manipulate_bytecode('_temp', mapping,
222 lambda bc: b'',
223 del_source=del_source)
224 test('_temp', mapping, bc_path)
225
226 @source_util.writes_bytecode_files
227 def _test_partial_magic(self, test, *, del_source=False):
228 # When their are less than 4 bytes to a .pyc, regenerate it if
229 # possible, else raise ImportError.
230 with source_util.create_modules('_temp') as mapping:
231 bc_path = self.manipulate_bytecode('_temp', mapping,
232 lambda bc: bc[:3],
233 del_source=del_source)
234 test('_temp', mapping, bc_path)
235
236 def _test_magic_only(self, test, *, del_source=False):
237 with source_util.create_modules('_temp') as mapping:
238 bc_path = self.manipulate_bytecode('_temp', mapping,
239 lambda bc: bc[:4],
240 del_source=del_source)
241 test('_temp', mapping, bc_path)
242
243 def _test_partial_timestamp(self, test, *, del_source=False):
244 with source_util.create_modules('_temp') as mapping:
245 bc_path = self.manipulate_bytecode('_temp', mapping,
246 lambda bc: bc[:7],
247 del_source=del_source)
248 test('_temp', mapping, bc_path)
249
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100250 def _test_partial_size(self, test, *, del_source=False):
251 with source_util.create_modules('_temp') as mapping:
252 bc_path = self.manipulate_bytecode('_temp', mapping,
253 lambda bc: bc[:11],
254 del_source=del_source)
255 test('_temp', mapping, bc_path)
256
Brett Cannon61b14252010-07-03 21:48:25 +0000257 def _test_no_marshal(self, *, del_source=False):
258 with source_util.create_modules('_temp') as mapping:
259 bc_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100260 lambda bc: bc[:12],
Brett Cannon61b14252010-07-03 21:48:25 +0000261 del_source=del_source)
262 file_path = mapping['_temp'] if not del_source else bc_path
263 with self.assertRaises(EOFError):
264 self.import_(file_path, '_temp')
265
266 def _test_non_code_marshal(self, *, del_source=False):
267 with source_util.create_modules('_temp') as mapping:
268 bytecode_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100269 lambda bc: bc[:12] + marshal.dumps(b'abcd'),
Brett Cannon61b14252010-07-03 21:48:25 +0000270 del_source=del_source)
271 file_path = mapping['_temp'] if not del_source else bytecode_path
Brett Cannonbbb66802012-04-12 21:09:01 -0400272 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000273 self.import_(file_path, '_temp')
Brett Cannonbbb66802012-04-12 21:09:01 -0400274 self.assertEqual(cm.exception.name, '_temp')
275 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000276
277 def _test_bad_marshal(self, *, del_source=False):
278 with source_util.create_modules('_temp') as mapping:
279 bytecode_path = self.manipulate_bytecode('_temp', mapping,
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100280 lambda bc: bc[:12] + b'<test>',
Brett Cannon61b14252010-07-03 21:48:25 +0000281 del_source=del_source)
282 file_path = mapping['_temp'] if not del_source else bytecode_path
Vinay Sajip5bdae3b2011-07-02 16:42:47 +0100283 with self.assertRaises(EOFError):
Brett Cannon61b14252010-07-03 21:48:25 +0000284 self.import_(file_path, '_temp')
285
286 def _test_bad_magic(self, test, *, del_source=False):
287 with source_util.create_modules('_temp') as mapping:
288 bc_path = self.manipulate_bytecode('_temp', mapping,
289 lambda bc: b'\x00\x00\x00\x00' + bc[4:])
290 test('_temp', mapping, bc_path)
291
292
293class SourceLoaderBadBytecodeTest(BadBytecodeTest):
294
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400295 loader = machinery.SourceFileLoader
Brett Cannon61b14252010-07-03 21:48:25 +0000296
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000297 @source_util.writes_bytecode_files
298 def test_empty_file(self):
299 # When a .pyc is empty, regenerate it if possible, else raise
300 # ImportError.
Brett Cannon61b14252010-07-03 21:48:25 +0000301 def test(name, mapping, bytecode_path):
302 self.import_(mapping[name], name)
303 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100304 self.assertGreater(len(file.read()), 12)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000305
Brett Cannon61b14252010-07-03 21:48:25 +0000306 self._test_empty_file(test)
307
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000308 def test_partial_magic(self):
Brett Cannon61b14252010-07-03 21:48:25 +0000309 def test(name, mapping, bytecode_path):
310 self.import_(mapping[name], name)
311 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100312 self.assertGreater(len(file.read()), 12)
Brett Cannon61b14252010-07-03 21:48:25 +0000313
314 self._test_partial_magic(test)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000315
316 @source_util.writes_bytecode_files
317 def test_magic_only(self):
318 # When there is only the magic number, regenerate the .pyc if possible,
319 # else raise EOFError.
Brett Cannon61b14252010-07-03 21:48:25 +0000320 def test(name, mapping, bytecode_path):
321 self.import_(mapping[name], name)
322 with open(bytecode_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100323 self.assertGreater(len(file.read()), 12)
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000324
Antoine Pitrou7c9907e2011-12-30 21:25:15 +0100325 self._test_magic_only(test)
326
Brett Cannon1262e7c2009-05-11 01:47:11 +0000327 @source_util.writes_bytecode_files
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000328 def test_bad_magic(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000329 # When the magic number is different, the bytecode should be
330 # regenerated.
Brett Cannon61b14252010-07-03 21:48:25 +0000331 def test(name, mapping, bytecode_path):
332 self.import_(mapping[name], name)
333 with open(bytecode_path, 'rb') as bytecode_file:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000334 self.assertEqual(bytecode_file.read(4), imp.get_magic())
335
Brett Cannon61b14252010-07-03 21:48:25 +0000336 self._test_bad_magic(test)
337
338 @source_util.writes_bytecode_files
339 def test_partial_timestamp(self):
340 # When the timestamp is partial, regenerate the .pyc, else
341 # raise EOFError.
342 def test(name, mapping, bc_path):
343 self.import_(mapping[name], name)
344 with open(bc_path, 'rb') as file:
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100345 self.assertGreater(len(file.read()), 12)
Brett Cannon61b14252010-07-03 21:48:25 +0000346
Antoine Pitrou7c9907e2011-12-30 21:25:15 +0100347 self._test_partial_timestamp(test)
348
Brett Cannon61b14252010-07-03 21:48:25 +0000349 @source_util.writes_bytecode_files
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100350 def test_partial_size(self):
351 # When the size is partial, regenerate the .pyc, else
352 # raise EOFError.
353 def test(name, mapping, bc_path):
354 self.import_(mapping[name], name)
355 with open(bc_path, 'rb') as file:
356 self.assertGreater(len(file.read()), 12)
357
358 self._test_partial_size(test)
359
360 @source_util.writes_bytecode_files
Brett Cannon61b14252010-07-03 21:48:25 +0000361 def test_no_marshal(self):
362 # When there is only the magic number and timestamp, raise EOFError.
363 self._test_no_marshal()
364
365 @source_util.writes_bytecode_files
366 def test_non_code_marshal(self):
367 self._test_non_code_marshal()
368 # XXX ImportError when sourceless
369
370 # [bad marshal]
371 @source_util.writes_bytecode_files
372 def test_bad_marshal(self):
373 # Bad marshal data should raise a ValueError.
374 self._test_bad_marshal()
375
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000376 # [bad timestamp]
Brett Cannon1262e7c2009-05-11 01:47:11 +0000377 @source_util.writes_bytecode_files
Brett Cannon61b14252010-07-03 21:48:25 +0000378 def test_old_timestamp(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000379 # When the timestamp is older than the source, bytecode should be
380 # regenerated.
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000381 zeros = b'\x00\x00\x00\x00'
Brett Cannon4ee2cda2009-02-01 03:08:31 +0000382 with source_util.create_modules('_temp') as mapping:
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000383 py_compile.compile(mapping['_temp'])
Barry Warsaw28a691b2010-04-17 00:19:56 +0000384 bytecode_path = imp.cache_from_source(mapping['_temp'])
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000385 with open(bytecode_path, 'r+b') as bytecode_file:
386 bytecode_file.seek(4)
387 bytecode_file.write(zeros)
388 self.import_(mapping['_temp'], '_temp')
389 source_mtime = os.path.getmtime(mapping['_temp'])
390 source_timestamp = importlib._w_long(source_mtime)
391 with open(bytecode_path, 'rb') as bytecode_file:
392 bytecode_file.seek(4)
393 self.assertEqual(bytecode_file.read(4), source_timestamp)
394
Brett Cannone52c9192009-11-07 23:55:05 +0000395 # [bytecode read-only]
396 @source_util.writes_bytecode_files
397 def test_read_only_bytecode(self):
Brett Cannon9b3e15f2010-02-19 16:01:06 +0000398 # When bytecode is read-only but should be rewritten, fail silently.
Brett Cannone52c9192009-11-07 23:55:05 +0000399 with source_util.create_modules('_temp') as mapping:
400 # Create bytecode that will need to be re-created.
401 py_compile.compile(mapping['_temp'])
Barry Warsaw28a691b2010-04-17 00:19:56 +0000402 bytecode_path = imp.cache_from_source(mapping['_temp'])
Brett Cannone52c9192009-11-07 23:55:05 +0000403 with open(bytecode_path, 'r+b') as bytecode_file:
404 bytecode_file.seek(0)
405 bytecode_file.write(b'\x00\x00\x00\x00')
406 # Make the bytecode read-only.
407 os.chmod(bytecode_path,
408 stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
409 try:
410 # Should not raise IOError!
411 self.import_(mapping['_temp'], '_temp')
412 finally:
413 # Make writable for eventual clean-up.
414 os.chmod(bytecode_path, stat.S_IWUSR)
415
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000416
Brett Cannon61b14252010-07-03 21:48:25 +0000417class SourcelessLoaderBadBytecodeTest(BadBytecodeTest):
418
Brett Cannon45a5e3a2012-07-20 14:48:53 -0400419 loader = machinery.SourcelessFileLoader
Brett Cannon61b14252010-07-03 21:48:25 +0000420
421 def test_empty_file(self):
422 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400423 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000424 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400425 self.assertEqual(cm.exception.name, name)
426 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000427
428 self._test_empty_file(test, del_source=True)
429
430 def test_partial_magic(self):
431 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400432 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000433 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400434 self.assertEqual(cm.exception.name, name)
435 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000436 self._test_partial_magic(test, del_source=True)
437
438 def test_magic_only(self):
439 def test(name, mapping, bytecode_path):
440 with self.assertRaises(EOFError):
441 self.import_(bytecode_path, name)
442
443 self._test_magic_only(test, del_source=True)
444
445 def test_bad_magic(self):
446 def test(name, mapping, bytecode_path):
Brett Cannonbbb66802012-04-12 21:09:01 -0400447 with self.assertRaises(ImportError) as cm:
Brett Cannon61b14252010-07-03 21:48:25 +0000448 self.import_(bytecode_path, name)
Brett Cannonbbb66802012-04-12 21:09:01 -0400449 self.assertEqual(cm.exception.name, name)
450 self.assertEqual(cm.exception.path, bytecode_path)
Brett Cannon61b14252010-07-03 21:48:25 +0000451
452 self._test_bad_magic(test, del_source=True)
453
454 def test_partial_timestamp(self):
455 def test(name, mapping, bytecode_path):
456 with self.assertRaises(EOFError):
457 self.import_(bytecode_path, name)
458
459 self._test_partial_timestamp(test, del_source=True)
460
Antoine Pitrou5136ac02012-01-13 18:52:16 +0100461 def test_partial_size(self):
462 def test(name, mapping, bytecode_path):
463 with self.assertRaises(EOFError):
464 self.import_(bytecode_path, name)
465
466 self._test_partial_size(test, del_source=True)
467
Brett Cannon61b14252010-07-03 21:48:25 +0000468 def test_no_marshal(self):
469 self._test_no_marshal(del_source=True)
470
471 def test_non_code_marshal(self):
472 self._test_non_code_marshal(del_source=True)
473
474
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000475def test_main():
476 from test.support import run_unittest
Brett Cannon61b14252010-07-03 21:48:25 +0000477 run_unittest(SimpleTest,
478 SourceLoaderBadBytecodeTest,
479 SourcelessLoaderBadBytecodeTest
Brett Cannon186335b2010-08-22 22:11:06 +0000480 )
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000481
482
483if __name__ == '__main__':
484 test_main()