mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 b063b02eab
			
		
	
	
		b063b02eab
		
			
		
	
	
	
	
		
			
			The error string on VxWorks is "no such file or directory" for FileNotFoundError. That is, the 1st letter of the error string has lower case.
		
			
				
	
	
		
			290 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import functools
 | |
| import importlib.util
 | |
| import os
 | |
| import py_compile
 | |
| import shutil
 | |
| import stat
 | |
| import subprocess
 | |
| import sys
 | |
| import tempfile
 | |
| import unittest
 | |
| 
 | |
| from test import support
 | |
| from test.support import os_helper, script_helper
 | |
| 
 | |
| 
 | |
| def without_source_date_epoch(fxn):
 | |
|     """Runs function with SOURCE_DATE_EPOCH unset."""
 | |
|     @functools.wraps(fxn)
 | |
|     def wrapper(*args, **kwargs):
 | |
|         with os_helper.EnvironmentVarGuard() as env:
 | |
|             env.unset('SOURCE_DATE_EPOCH')
 | |
|             return fxn(*args, **kwargs)
 | |
|     return wrapper
 | |
| 
 | |
| 
 | |
| def with_source_date_epoch(fxn):
 | |
|     """Runs function with SOURCE_DATE_EPOCH set."""
 | |
|     @functools.wraps(fxn)
 | |
|     def wrapper(*args, **kwargs):
 | |
|         with os_helper.EnvironmentVarGuard() as env:
 | |
|             env['SOURCE_DATE_EPOCH'] = '123456789'
 | |
|             return fxn(*args, **kwargs)
 | |
|     return wrapper
 | |
| 
 | |
| 
 | |
| # Run tests with SOURCE_DATE_EPOCH set or unset explicitly.
 | |
| class SourceDateEpochTestMeta(type(unittest.TestCase)):
 | |
|     def __new__(mcls, name, bases, dct, *, source_date_epoch):
 | |
|         cls = super().__new__(mcls, name, bases, dct)
 | |
| 
 | |
|         for attr in dir(cls):
 | |
|             if attr.startswith('test_'):
 | |
|                 meth = getattr(cls, attr)
 | |
|                 if source_date_epoch:
 | |
|                     wrapper = with_source_date_epoch(meth)
 | |
|                 else:
 | |
|                     wrapper = without_source_date_epoch(meth)
 | |
|                 setattr(cls, attr, wrapper)
 | |
| 
 | |
|         return cls
 | |
| 
 | |
| 
 | |
| class PyCompileTestsBase:
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.directory = tempfile.mkdtemp(dir=os.getcwd())
 | |
|         self.source_path = os.path.join(self.directory, '_test.py')
 | |
|         self.pyc_path = self.source_path + 'c'
 | |
|         self.cache_path = importlib.util.cache_from_source(self.source_path)
 | |
|         self.cwd_drive = os.path.splitdrive(os.getcwd())[0]
 | |
|         # In these tests we compute relative paths.  When using Windows, the
 | |
|         # current working directory path and the 'self.source_path' might be
 | |
|         # on different drives.  Therefore we need to switch to the drive where
 | |
|         # the temporary source file lives.
 | |
|         drive = os.path.splitdrive(self.source_path)[0]
 | |
|         if drive:
 | |
|             os.chdir(drive)
 | |
|         with open(self.source_path, 'w') as file:
 | |
|             file.write('x = 123\n')
 | |
| 
 | |
|     def tearDown(self):
 | |
|         shutil.rmtree(self.directory)
 | |
|         if self.cwd_drive:
 | |
|             os.chdir(self.cwd_drive)
 | |
| 
 | |
|     def test_absolute_path(self):
 | |
|         py_compile.compile(self.source_path, self.pyc_path)
 | |
|         self.assertTrue(os.path.exists(self.pyc_path))
 | |
|         self.assertFalse(os.path.exists(self.cache_path))
 | |
| 
 | |
|     def test_do_not_overwrite_symlinks(self):
 | |
|         # In the face of a cfile argument being a symlink, bail out.
 | |
|         # Issue #17222
 | |
|         try:
 | |
|             os.symlink(self.pyc_path + '.actual', self.pyc_path)
 | |
|         except (NotImplementedError, OSError):
 | |
|             self.skipTest('need to be able to create a symlink for a file')
 | |
|         else:
 | |
|             assert os.path.islink(self.pyc_path)
 | |
|             with self.assertRaises(FileExistsError):
 | |
|                 py_compile.compile(self.source_path, self.pyc_path)
 | |
| 
 | |
|     @unittest.skipIf(not os.path.exists(os.devnull) or os.path.isfile(os.devnull),
 | |
|                      'requires os.devnull and for it to be a non-regular file')
 | |
|     def test_do_not_overwrite_nonregular_files(self):
 | |
|         # In the face of a cfile argument being a non-regular file, bail out.
 | |
|         # Issue #17222
 | |
|         with self.assertRaises(FileExistsError):
 | |
|             py_compile.compile(self.source_path, os.devnull)
 | |
| 
 | |
|     def test_cache_path(self):
 | |
|         py_compile.compile(self.source_path)
 | |
|         self.assertTrue(os.path.exists(self.cache_path))
 | |
| 
 | |
|     def test_cwd(self):
 | |
|         with os_helper.change_cwd(self.directory):
 | |
|             py_compile.compile(os.path.basename(self.source_path),
 | |
|                                os.path.basename(self.pyc_path))
 | |
|         self.assertTrue(os.path.exists(self.pyc_path))
 | |
|         self.assertFalse(os.path.exists(self.cache_path))
 | |
| 
 | |
|     def test_relative_path(self):
 | |
|         py_compile.compile(os.path.relpath(self.source_path),
 | |
|                            os.path.relpath(self.pyc_path))
 | |
|         self.assertTrue(os.path.exists(self.pyc_path))
 | |
|         self.assertFalse(os.path.exists(self.cache_path))
 | |
| 
 | |
|     @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
 | |
|                      'non-root user required')
 | |
|     @unittest.skipIf(os.name == 'nt',
 | |
|                      'cannot control directory permissions on Windows')
 | |
|     def test_exceptions_propagate(self):
 | |
|         # Make sure that exceptions raised thanks to issues with writing
 | |
|         # bytecode.
 | |
|         # http://bugs.python.org/issue17244
 | |
|         mode = os.stat(self.directory)
 | |
|         os.chmod(self.directory, stat.S_IREAD)
 | |
|         try:
 | |
|             with self.assertRaises(IOError):
 | |
|                 py_compile.compile(self.source_path, self.pyc_path)
 | |
|         finally:
 | |
|             os.chmod(self.directory, mode.st_mode)
 | |
| 
 | |
|     def test_bad_coding(self):
 | |
|         bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py')
 | |
|         with support.captured_stderr():
 | |
|             self.assertIsNone(py_compile.compile(bad_coding, doraise=False))
 | |
|         self.assertFalse(os.path.exists(
 | |
|             importlib.util.cache_from_source(bad_coding)))
 | |
| 
 | |
|     def test_source_date_epoch(self):
 | |
|         py_compile.compile(self.source_path, self.pyc_path)
 | |
|         self.assertTrue(os.path.exists(self.pyc_path))
 | |
|         self.assertFalse(os.path.exists(self.cache_path))
 | |
|         with open(self.pyc_path, 'rb') as fp:
 | |
|             flags = importlib._bootstrap_external._classify_pyc(
 | |
|                 fp.read(), 'test', {})
 | |
|         if os.environ.get('SOURCE_DATE_EPOCH'):
 | |
|             expected_flags = 0b11
 | |
|         else:
 | |
|             expected_flags = 0b00
 | |
| 
 | |
|         self.assertEqual(flags, expected_flags)
 | |
| 
 | |
|     @unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O')
 | |
|     def test_double_dot_no_clobber(self):
 | |
|         # http://bugs.python.org/issue22966
 | |
|         # py_compile foo.bar.py -> __pycache__/foo.cpython-34.pyc
 | |
|         weird_path = os.path.join(self.directory, 'foo.bar.py')
 | |
|         cache_path = importlib.util.cache_from_source(weird_path)
 | |
|         pyc_path = weird_path + 'c'
 | |
|         head, tail = os.path.split(cache_path)
 | |
|         penultimate_tail = os.path.basename(head)
 | |
|         self.assertEqual(
 | |
|             os.path.join(penultimate_tail, tail),
 | |
|             os.path.join(
 | |
|                 '__pycache__',
 | |
|                 'foo.bar.{}.pyc'.format(sys.implementation.cache_tag)))
 | |
|         with open(weird_path, 'w') as file:
 | |
|             file.write('x = 123\n')
 | |
|         py_compile.compile(weird_path)
 | |
|         self.assertTrue(os.path.exists(cache_path))
 | |
|         self.assertFalse(os.path.exists(pyc_path))
 | |
| 
 | |
|     def test_optimization_path(self):
 | |
|         # Specifying optimized bytecode should lead to a path reflecting that.
 | |
|         self.assertIn('opt-2', py_compile.compile(self.source_path, optimize=2))
 | |
| 
 | |
|     def test_invalidation_mode(self):
 | |
|         py_compile.compile(
 | |
|             self.source_path,
 | |
|             invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
 | |
|         )
 | |
|         with open(self.cache_path, 'rb') as fp:
 | |
|             flags = importlib._bootstrap_external._classify_pyc(
 | |
|                 fp.read(), 'test', {})
 | |
|         self.assertEqual(flags, 0b11)
 | |
|         py_compile.compile(
 | |
|             self.source_path,
 | |
|             invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH,
 | |
|         )
 | |
|         with open(self.cache_path, 'rb') as fp:
 | |
|             flags = importlib._bootstrap_external._classify_pyc(
 | |
|                 fp.read(), 'test', {})
 | |
|         self.assertEqual(flags, 0b1)
 | |
| 
 | |
|     def test_quiet(self):
 | |
|         bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py')
 | |
|         with support.captured_stderr() as stderr:
 | |
|             self.assertIsNone(py_compile.compile(bad_coding, doraise=False, quiet=2))
 | |
|             self.assertIsNone(py_compile.compile(bad_coding, doraise=True, quiet=2))
 | |
|             self.assertEqual(stderr.getvalue(), '')
 | |
|             with self.assertRaises(py_compile.PyCompileError):
 | |
|                 py_compile.compile(bad_coding, doraise=True, quiet=1)
 | |
| 
 | |
| 
 | |
| class PyCompileTestsWithSourceEpoch(PyCompileTestsBase,
 | |
|                                     unittest.TestCase,
 | |
|                                     metaclass=SourceDateEpochTestMeta,
 | |
|                                     source_date_epoch=True):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class PyCompileTestsWithoutSourceEpoch(PyCompileTestsBase,
 | |
|                                        unittest.TestCase,
 | |
|                                        metaclass=SourceDateEpochTestMeta,
 | |
|                                        source_date_epoch=False):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class PyCompileCLITestCase(unittest.TestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.directory = tempfile.mkdtemp()
 | |
|         self.source_path = os.path.join(self.directory, '_test.py')
 | |
|         self.cache_path = importlib.util.cache_from_source(self.source_path)
 | |
|         with open(self.source_path, 'w') as file:
 | |
|             file.write('x = 123\n')
 | |
| 
 | |
|     def tearDown(self):
 | |
|         os_helper.rmtree(self.directory)
 | |
| 
 | |
|     def pycompilecmd(self, *args, **kwargs):
 | |
|         # assert_python_* helpers don't return proc object. We'll just use
 | |
|         # subprocess.run() instead of spawn_python() and its friends to test
 | |
|         # stdin support of the CLI.
 | |
|         if args and args[0] == '-' and 'input' in kwargs:
 | |
|             return subprocess.run([sys.executable, '-m', 'py_compile', '-'],
 | |
|                                   input=kwargs['input'].encode(),
 | |
|                                   capture_output=True)
 | |
|         return script_helper.assert_python_ok('-m', 'py_compile', *args, **kwargs)
 | |
| 
 | |
|     def pycompilecmd_failure(self, *args):
 | |
|         return script_helper.assert_python_failure('-m', 'py_compile', *args)
 | |
| 
 | |
|     def test_stdin(self):
 | |
|         result = self.pycompilecmd('-', input=self.source_path)
 | |
|         self.assertEqual(result.returncode, 0)
 | |
|         self.assertEqual(result.stdout, b'')
 | |
|         self.assertEqual(result.stderr, b'')
 | |
|         self.assertTrue(os.path.exists(self.cache_path))
 | |
| 
 | |
|     def test_with_files(self):
 | |
|         rc, stdout, stderr = self.pycompilecmd(self.source_path, self.source_path)
 | |
|         self.assertEqual(rc, 0)
 | |
|         self.assertEqual(stdout, b'')
 | |
|         self.assertEqual(stderr, b'')
 | |
|         self.assertTrue(os.path.exists(self.cache_path))
 | |
| 
 | |
|     def test_bad_syntax(self):
 | |
|         bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py')
 | |
|         rc, stdout, stderr = self.pycompilecmd_failure(bad_syntax)
 | |
|         self.assertEqual(rc, 1)
 | |
|         self.assertEqual(stdout, b'')
 | |
|         self.assertIn(b'SyntaxError', stderr)
 | |
| 
 | |
|     def test_bad_syntax_with_quiet(self):
 | |
|         bad_syntax = os.path.join(os.path.dirname(__file__), 'badsyntax_3131.py')
 | |
|         rc, stdout, stderr = self.pycompilecmd_failure('-q', bad_syntax)
 | |
|         self.assertEqual(rc, 1)
 | |
|         self.assertEqual(stdout, b'')
 | |
|         self.assertEqual(stderr, b'')
 | |
| 
 | |
|     def test_file_not_exists(self):
 | |
|         should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
 | |
|         rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists)
 | |
|         self.assertEqual(rc, 1)
 | |
|         self.assertEqual(stdout, b'')
 | |
|         self.assertIn(b'no such file or directory', stderr.lower())
 | |
| 
 | |
|     def test_file_not_exists_with_quiet(self):
 | |
|         should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
 | |
|         rc, stdout, stderr = self.pycompilecmd_failure('-q', self.source_path, should_not_exists)
 | |
|         self.assertEqual(rc, 1)
 | |
|         self.assertEqual(stdout, b'')
 | |
|         self.assertEqual(stderr, b'')
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 |