|
11 | 11 | import time
|
12 | 12 | import unittest
|
13 | 13 | import io
|
| 14 | +import errno |
14 | 15 |
|
15 | 16 | from unittest import mock, skipUnless
|
16 | 17 | try:
|
@@ -41,20 +42,57 @@ def setUp(self):
|
41 | 42 | os.mkdir(self.subdirectory)
|
42 | 43 | self.source_path3 = os.path.join(self.subdirectory, '_test3.py')
|
43 | 44 | shutil.copyfile(self.source_path, self.source_path3)
|
44 |
| - many_directories = [str(number) for number in range(1, 100)] |
45 |
| - self.long_path = os.path.join(self.directory, |
46 |
| - "long", |
47 |
| - *many_directories) |
48 |
| - os.makedirs(self.long_path) |
49 |
| - self.source_path_long = os.path.join(self.long_path, '_test4.py') |
50 |
| - shutil.copyfile(self.source_path, self.source_path_long) |
51 |
| - self.bc_path_long = importlib.util.cache_from_source( |
52 |
| - self.source_path_long |
53 |
| - ) |
54 | 45 |
|
55 | 46 | def tearDown(self):
|
56 | 47 | shutil.rmtree(self.directory)
|
57 | 48 |
|
| 49 | + def create_long_path(self): |
| 50 | + long_path = os.path.join(self.directory, "long") |
| 51 | + |
| 52 | + # Create a long path, 10 directories at a time. |
| 53 | + # It will be 100 directories deep, or shorter if the OS limits it. |
| 54 | + for i in range(10): |
| 55 | + longer_path = os.path.join( |
| 56 | + long_path, *(f"long_directory_{i}_{j}" for j in range(10)) |
| 57 | + ) |
| 58 | + |
| 59 | + # Check if we can open __pycache__/*.pyc. |
| 60 | + # Also, put in the source file that we want to compile |
| 61 | + longer_source = os.path.join(longer_path, '_test_long.py') |
| 62 | + longer_cache = importlib.util.cache_from_source(longer_source) |
| 63 | + try: |
| 64 | + os.makedirs(longer_path) |
| 65 | + shutil.copyfile(self.source_path, longer_source) |
| 66 | + os.makedirs(os.path.dirname(longer_cache)) |
| 67 | + # Make sure we can write to the cache |
| 68 | + with open(longer_cache, 'w'): |
| 69 | + pass |
| 70 | + except FileNotFoundError: |
| 71 | + # On Windows, a FileNotFoundError("The filename or extension |
| 72 | + # is too long") is raised for long paths |
| 73 | + if sys.platform == "win32": |
| 74 | + break |
| 75 | + else: |
| 76 | + raise |
| 77 | + except OSError as exc: |
| 78 | + if exc.errno == errno.ENAMETOOLONG: |
| 79 | + break |
| 80 | + else: |
| 81 | + raise |
| 82 | + |
| 83 | + # Remove the __pycache__ |
| 84 | + shutil.rmtree(os.path.dirname(longer_cache)) |
| 85 | + |
| 86 | + long_path = longer_path |
| 87 | + long_source = longer_source |
| 88 | + long_cache = longer_cache |
| 89 | + |
| 90 | + if i < 2: |
| 91 | + raise ValueError('Path limit is too short') |
| 92 | + |
| 93 | + self.source_path_long = long_source |
| 94 | + self.bc_path_long = long_cache |
| 95 | + |
58 | 96 | def add_bad_source_file(self):
|
59 | 97 | self.bad_source_path = os.path.join(self.directory, '_test_bad.py')
|
60 | 98 | with open(self.bad_source_path, 'w') as file:
|
@@ -204,13 +242,14 @@ def test_compile_missing_multiprocessing(self, compile_file_mock):
|
204 | 242 | compileall.compile_dir(self.directory, quiet=True, workers=5)
|
205 | 243 | self.assertTrue(compile_file_mock.called)
|
206 | 244 |
|
207 |
| - def text_compile_dir_maxlevels(self): |
| 245 | + def test_compile_dir_maxlevels(self): |
208 | 246 | # Test the actual impact of maxlevels attr
|
| 247 | + self.create_long_path() |
209 | 248 | compileall.compile_dir(os.path.join(self.directory, "long"),
|
210 | 249 | maxlevels=10, quiet=True)
|
211 | 250 | self.assertFalse(os.path.isfile(self.bc_path_long))
|
212 | 251 | compileall.compile_dir(os.path.join(self.directory, "long"),
|
213 |
| - maxlevels=110, quiet=True) |
| 252 | + quiet=True) |
214 | 253 | self.assertTrue(os.path.isfile(self.bc_path_long))
|
215 | 254 |
|
216 | 255 | def test_strip_only(self):
|
|
0 commit comments