diff options
author | Petr Viktorin <encukou@gmail.com> | 2019-09-26 09:53:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-26 09:53:51 (GMT) |
commit | 4267c989e7fc6cd528e8a1d04a07fac5cca85ec7 (patch) | |
tree | acb2d4b90ec5e7dcdd31e0e0d2da4c7130da4a45 | |
parent | a7414571a113815033fdc9f7abb3f5a24e44c472 (diff) | |
download | cpython-4267c989e7fc6cd528e8a1d04a07fac5cca85ec7.zip cpython-4267c989e7fc6cd528e8a1d04a07fac5cca85ec7.tar.gz cpython-4267c989e7fc6cd528e8a1d04a07fac5cca85ec7.tar.bz2 |
bpo-38112: compileall: Skip long path path on Windows if the path can't be created (GH-16414)
This avoids the buildbot failure on Windows:
```
FileNotFoundError: [WinError 206] The filename or extension is too long: 'd:\\temp\\tmp5r3z438t\\long\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10\\11\\12\\13\\14\\15\\16\\17\\18\\19\\20\\21\\22\\23\\24\\25\\26\\27\\28\\29\\30\\31\\32\\33\\34\\35\\36\\37\\38\\39\\40\\41\\42\\43\\44\\45\\46\\47\\48\\49\\50\\51\\52\\53\\54\\55\\56\\57\\58\\59\\60\\61\\62\\63\\64\\65\\66\\67\\68\\69\\70\\71\\72\\73\\74\\75\\76\\77\\78'
```
Creates a path that's long but avoids OS restrictions.
https://bugs.python.org/issue38112
-rw-r--r-- | Lib/test/test_compileall.py | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index af885c5..205457f 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -11,6 +11,7 @@ import tempfile import time import unittest import io +import errno from unittest import mock, skipUnless try: @@ -41,20 +42,57 @@ class CompileallTestsBase: os.mkdir(self.subdirectory) self.source_path3 = os.path.join(self.subdirectory, '_test3.py') shutil.copyfile(self.source_path, self.source_path3) - many_directories = [str(number) for number in range(1, 100)] - self.long_path = os.path.join(self.directory, - "long", - *many_directories) - os.makedirs(self.long_path) - self.source_path_long = os.path.join(self.long_path, '_test4.py') - shutil.copyfile(self.source_path, self.source_path_long) - self.bc_path_long = importlib.util.cache_from_source( - self.source_path_long - ) def tearDown(self): shutil.rmtree(self.directory) + def create_long_path(self): + long_path = os.path.join(self.directory, "long") + + # Create a long path, 10 directories at a time. + # It will be 100 directories deep, or shorter if the OS limits it. + for i in range(10): + longer_path = os.path.join( + long_path, *(f"long_directory_{i}_{j}" for j in range(10)) + ) + + # Check if we can open __pycache__/*.pyc. + # Also, put in the source file that we want to compile + longer_source = os.path.join(longer_path, '_test_long.py') + longer_cache = importlib.util.cache_from_source(longer_source) + try: + os.makedirs(longer_path) + shutil.copyfile(self.source_path, longer_source) + os.makedirs(os.path.dirname(longer_cache)) + # Make sure we can write to the cache + with open(longer_cache, 'w'): + pass + except FileNotFoundError: + # On Windows, a FileNotFoundError("The filename or extension + # is too long") is raised for long paths + if sys.platform == "win32": + break + else: + raise + except OSError as exc: + if exc.errno == errno.ENAMETOOLONG: + break + else: + raise + + # Remove the __pycache__ + shutil.rmtree(os.path.dirname(longer_cache)) + + long_path = longer_path + long_source = longer_source + long_cache = longer_cache + + if i < 2: + raise ValueError('Path limit is too short') + + self.source_path_long = long_source + self.bc_path_long = long_cache + def add_bad_source_file(self): self.bad_source_path = os.path.join(self.directory, '_test_bad.py') with open(self.bad_source_path, 'w') as file: @@ -204,13 +242,14 @@ class CompileallTestsBase: compileall.compile_dir(self.directory, quiet=True, workers=5) self.assertTrue(compile_file_mock.called) - def text_compile_dir_maxlevels(self): + def test_compile_dir_maxlevels(self): # Test the actual impact of maxlevels attr + self.create_long_path() compileall.compile_dir(os.path.join(self.directory, "long"), maxlevels=10, quiet=True) self.assertFalse(os.path.isfile(self.bc_path_long)) compileall.compile_dir(os.path.join(self.directory, "long"), - maxlevels=110, quiet=True) + quiet=True) self.assertTrue(os.path.isfile(self.bc_path_long)) def test_strip_only(self): |