|
2 | 2 | import compileall2 as compileall
|
3 | 3 | import importlib.util
|
4 | 4 | import test.test_importlib.util
|
| 5 | +import marshal |
5 | 6 | import os
|
6 | 7 | import pathlib
|
7 | 8 | import py_compile
|
@@ -39,6 +40,19 @@ def _optim_args_from_interpreter_flags():
|
39 | 40 | args.append('-' + 'O' * value)
|
40 | 41 | return args
|
41 | 42 |
|
| 43 | +# Backported from Lib/test/test_importlib/util.py |
| 44 | +# Added in: https://github.com/python/cpython/pull/18676/files |
| 45 | +def get_code_from_pyc(pyc_path): |
| 46 | + """Reads a pyc file and returns the unmarshalled code object within. |
| 47 | + No header validation is performed. |
| 48 | + """ |
| 49 | + with open(pyc_path, 'rb') as pyc_f: |
| 50 | + if compileall.PY37: |
| 51 | + pyc_f.seek(16) |
| 52 | + else: |
| 53 | + pyc_f.seek(12) |
| 54 | + return marshal.load(pyc_f) |
| 55 | + |
42 | 56 | # Use the original one for Python > 3.5 and backported function otherwise
|
43 | 57 | if compileall.PY36:
|
44 | 58 | optim_args_from_interpreter_flags = support.optim_args_from_interpreter_flags
|
@@ -274,6 +288,47 @@ def test_compile_dir_maxlevels(self):
|
274 | 288 | compileall.compile_dir(self.directory, quiet=True, maxlevels=depth)
|
275 | 289 | self.assertTrue(os.path.isfile(pyc_filename))
|
276 | 290 |
|
| 291 | + def _test_ddir_only(self, *, ddir, parallel=True): |
| 292 | + """Recursive compile_dir ddir must contain package paths; bpo39769.""" |
| 293 | + fullpath = ["test", "foo"] |
| 294 | + path = self.directory |
| 295 | + mods = [] |
| 296 | + for subdir in fullpath: |
| 297 | + path = os.path.join(path, subdir) |
| 298 | + os.mkdir(path) |
| 299 | + script_helper.make_script(path, "__init__", "") |
| 300 | + mods.append(script_helper.make_script(path, "mod", |
| 301 | + "def fn(): 1/0\nfn()\n")) |
| 302 | + compileall.compile_dir( |
| 303 | + self.directory, quiet=True, ddir=ddir, |
| 304 | + workers=2 if parallel else 1) |
| 305 | + self.assertTrue(mods) |
| 306 | + for mod in mods: |
| 307 | + self.assertTrue(mod.startswith(self.directory), mod) |
| 308 | + modcode = importlib.util.cache_from_source(mod) |
| 309 | + modpath = mod[len(self.directory+os.sep):] |
| 310 | + _, _, err = script_helper.assert_python_failure(modcode) |
| 311 | + expected_in = os.path.join(ddir, modpath) |
| 312 | + mod_code_obj = get_code_from_pyc(modcode) |
| 313 | + self.assertEqual(mod_code_obj.co_filename, expected_in) |
| 314 | + self.assertIn('"{}"'.format(expected_in), os.fsdecode(err)) |
| 315 | + |
| 316 | + def test_ddir_only_one_worker(self): |
| 317 | + """Recursive compile_dir ddir= contains package paths; bpo39769.""" |
| 318 | + return self._test_ddir_only(ddir="<a prefix>", parallel=False) |
| 319 | + |
| 320 | + def test_ddir_multiple_workers(self): |
| 321 | + """Recursive compile_dir ddir= contains package paths; bpo39769.""" |
| 322 | + return self._test_ddir_only(ddir="<a prefix>", parallel=True) |
| 323 | + |
| 324 | + def test_ddir_empty_only_one_worker(self): |
| 325 | + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" |
| 326 | + return self._test_ddir_only(ddir="", parallel=False) |
| 327 | + |
| 328 | + def test_ddir_empty_multiple_workers(self): |
| 329 | + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" |
| 330 | + return self._test_ddir_only(ddir="", parallel=True) |
| 331 | + |
277 | 332 | def test_strip_only(self):
|
278 | 333 | fullpath = ["test", "build", "real", "path"]
|
279 | 334 | path = os.path.join(self.directory, *fullpath)
|
|
0 commit comments