mirror of https://github.com/python/cpython
gh-105931: Fix surprising compileall stripdir behaviour (GH-108671)
Before, the '-s STRIPDIR' option on compileall lead to some surprising results as it only strips away path components that match, but leaves alone the non-matching ones interspersed in between. For example, with: python -m compileall -s/path/to/another/src /path/to/build/src/file.py The resulting written path will be: build/file.py This fix only strips directories that are a fully matching prefix of the source path. If a stripdir is provided that is not a valid prefix, a warning will be displayed (which can be silenced with '-qq').
This commit is contained in:
parent
52e902ccf0
commit
3726cb0f14
|
@ -172,13 +172,13 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
|
|||
if stripdir is not None:
|
||||
fullname_parts = fullname.split(os.path.sep)
|
||||
stripdir_parts = stripdir.split(os.path.sep)
|
||||
ddir_parts = list(fullname_parts)
|
||||
|
||||
for spart, opart in zip(stripdir_parts, fullname_parts):
|
||||
if spart == opart:
|
||||
ddir_parts.remove(spart)
|
||||
|
||||
dfile = os.path.join(*ddir_parts)
|
||||
if stripdir_parts != fullname_parts[:len(stripdir_parts)]:
|
||||
if quiet < 2:
|
||||
print("The stripdir path {!r} is not a valid prefix for "
|
||||
"source path {!r}; ignoring".format(stripdir, fullname))
|
||||
else:
|
||||
dfile = os.path.join(*fullname_parts[len(stripdir_parts):])
|
||||
|
||||
if prependdir is not None:
|
||||
if dfile is None:
|
||||
|
|
|
@ -362,6 +362,29 @@ class CompileallTestsBase:
|
|||
str(err, encoding=sys.getdefaultencoding())
|
||||
)
|
||||
|
||||
def test_strip_only_invalid(self):
|
||||
fullpath = ["test", "build", "real", "path"]
|
||||
path = os.path.join(self.directory, *fullpath)
|
||||
os.makedirs(path)
|
||||
script = script_helper.make_script(path, "test", "1 / 0")
|
||||
bc = importlib.util.cache_from_source(script)
|
||||
stripdir = os.path.join(self.directory, *(fullpath[:2] + ['fake']))
|
||||
compileall.compile_dir(path, quiet=True, stripdir=stripdir)
|
||||
rc, out, err = script_helper.assert_python_failure(bc)
|
||||
expected_not_in = os.path.join(self.directory, *fullpath[2:])
|
||||
self.assertIn(
|
||||
path,
|
||||
str(err, encoding=sys.getdefaultencoding())
|
||||
)
|
||||
self.assertNotIn(
|
||||
expected_not_in,
|
||||
str(err, encoding=sys.getdefaultencoding())
|
||||
)
|
||||
self.assertNotIn(
|
||||
stripdir,
|
||||
str(err, encoding=sys.getdefaultencoding())
|
||||
)
|
||||
|
||||
def test_prepend_only(self):
|
||||
fullpath = ["test", "build", "real", "path"]
|
||||
path = os.path.join(self.directory, *fullpath)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
Change :mod:`compileall` to only strip the stripdir prefix from the full path
|
||||
recorded in the compiled ``.pyc`` file, when the prefix matches the start of
|
||||
the full path in its entirety. When the prefix does not match, no stripping is
|
||||
performed and a warning to this effect is displayed.
|
||||
|
||||
Previously all path components of the stripdir prefix that matched the full
|
||||
path were removed, while those that did not match were left alone (including
|
||||
ones interspersed between matching components).
|
Loading…
Reference in New Issue