diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -17,16 +17,45 @@ try: from concurrent.futures import ProcessPoolExecutor _have_multiprocessing = True except ImportError: _have_multiprocessing = False from test import support from test.support import script_helper + +def check_sys_path_writable(): + for path in filter(os.path.isdir, sys.path): + directory_created = False + directory = pathlib.Path(path) / '__pycache__' + path = directory / 'test.try' + try: + if not directory.is_dir(): + directory.mkdir() + directory_created = True + with path.open('w') as file: + file.write('# for test_compileall') + except OSError: + sys_path_writable = False + break + finally: + support.unlink(str(path)) + if directory_created: + directory.rmdir() + else: + sys_path_writable = True + return sys_path_writable + +skip_if_sys_path_not_writable = unittest.skipUnless( + check_sys_path_writable(), + 'not all entries on sys.path are writable' +) + + class CompileallTests(unittest.TestCase): def setUp(self): self.directory = tempfile.mkdtemp() self.source_path = os.path.join(self.directory, '_test.py') self.bc_path = importlib.util.cache_from_source(self.source_path) with open(self.source_path, 'w') as file: file.write('x = 123\n') @@ -97,16 +126,17 @@ class CompileallTests(unittest.TestCase) os.unlink(self.bc_path2) # Test against bad files self.add_bad_source_file() self.assertFalse(compileall.compile_file(self.bad_source_path, force=False, quiet=2)) self.assertFalse(compileall.compile_dir(self.directory, force=False, quiet=2)) + @skip_if_sys_path_not_writable def test_compile_path(self): # Exclude Lib/test/ which contains invalid Python files like # Lib/test/badsyntax_pep3120.py testdir = os.path.realpath(os.path.dirname(__file__)) if testdir in sys.path: self.addCleanup(setattr, sys, 'path', sys.path) sys.path = list(sys.path) @@ -198,43 +228,16 @@ class EncodingTest(unittest.TestCase): compileall.compile_dir(self.directory) finally: sys.stdout = orig_stdout class CommandLineTests(unittest.TestCase): """Test compileall's CLI.""" - @classmethod - def setUpClass(cls): - for path in filter(os.path.isdir, sys.path): - directory_created = False - directory = pathlib.Path(path) / '__pycache__' - path = directory / 'test.try' - try: - if not directory.is_dir(): - directory.mkdir() - directory_created = True - with path.open('w') as file: - file.write('# for test_compileall') - except OSError: - sys_path_writable = False - break - finally: - support.unlink(str(path)) - if directory_created: - directory.rmdir() - else: - sys_path_writable = True - cls._sys_path_writable = sys_path_writable - - def _skip_if_sys_path_not_writable(self): - if not self._sys_path_writable: - raise unittest.SkipTest('not all entries on sys.path are writable') - def _get_run_args(self, args): return [*support.optim_args_from_interpreter_flags(), '-S', '-m', 'compileall', *args] def assertRunOK(self, *args, **env_vars): rc, out, err = script_helper.assert_python_ok( *self._get_run_args(args), **env_vars) @@ -259,44 +262,44 @@ class CommandLineTests(unittest.TestCase self.addCleanup(support.rmtree, self.directory) self.pkgdir = os.path.join(self.directory, 'foo') os.mkdir(self.pkgdir) self.pkgdir_cachedir = os.path.join(self.pkgdir, '__pycache__') # Create the __init__.py and a package module. self.initfn = script_helper.make_script(self.pkgdir, '__init__', '') self.barfn = script_helper.make_script(self.pkgdir, 'bar', '') + @skip_if_sys_path_not_writable def test_no_args_compiles_path(self): # Note that -l is implied for the no args case. - self._skip_if_sys_path_not_writable() bazfn = script_helper.make_script(self.directory, 'baz', '') self.assertRunOK(PYTHONPATH=self.directory) self.assertCompiled(bazfn) self.assertNotCompiled(self.initfn) self.assertNotCompiled(self.barfn) + @skip_if_sys_path_not_writable def test_no_args_respects_force_flag(self): - self._skip_if_sys_path_not_writable() bazfn = script_helper.make_script(self.directory, 'baz', '') self.assertRunOK(PYTHONPATH=self.directory) pycpath = importlib.util.cache_from_source(bazfn) # Set atime/mtime backward to avoid file timestamp resolution issues os.utime(pycpath, (time.time()-60,)*2) mtime = os.stat(pycpath).st_mtime # Without force, no recompilation self.assertRunOK(PYTHONPATH=self.directory) mtime2 = os.stat(pycpath).st_mtime self.assertEqual(mtime, mtime2) # Now force it. self.assertRunOK('-f', PYTHONPATH=self.directory) mtime2 = os.stat(pycpath).st_mtime self.assertNotEqual(mtime, mtime2) + @skip_if_sys_path_not_writable def test_no_args_respects_quiet_flag(self): - self._skip_if_sys_path_not_writable() script_helper.make_script(self.directory, 'baz', '') noisy = self.assertRunOK(PYTHONPATH=self.directory) self.assertIn(b'Listing ', noisy) quiet = self.assertRunOK('-q', PYTHONPATH=self.directory) self.assertNotIn(b'Listing ', quiet) # Ensure that the default behavior of compileall's CLI is to create # PEP 3147/PEP 488 pyc files.