diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 20 | ||||
-rw-r--r-- | Lib/py_compile.py | 10 | ||||
-rw-r--r-- | Lib/test/test_py_compile.py | 17 |
3 files changed, 33 insertions, 14 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 03ca79f..77c14bc 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -474,6 +474,18 @@ def _get_sourcefile(bytecode_path): return source_path if _path_isfile(source_stats) else bytecode_path +def _calc_mode(path): + """Calculate the mode permissions for a bytecode file.""" + try: + mode = _os.stat(path).st_mode + except OSError: + mode = 0o666 + # We always ensure write access so we can update cached files + # later even when the source files are read-only on Windows (#6074) + mode |= 0o200 + return mode + + def _verbose_message(message, *args, verbosity=1): """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" if sys.flags.verbose >= verbosity: @@ -1060,13 +1072,7 @@ class SourceFileLoader(FileLoader, SourceLoader): def _cache_bytecode(self, source_path, bytecode_path, data): # Adapt between the two APIs - try: - mode = _os.stat(source_path).st_mode - except OSError: - mode = 0o666 - # We always ensure write access so we can update cached files - # later even when the source files are read-only on Windows (#6074) - mode |= 0o200 + mode = _calc_mode(source_path) return self.set_data(bytecode_path, data, _mode=mode) def set_data(self, path, data, *, _mode=0o666): diff --git a/Lib/py_compile.py b/Lib/py_compile.py index d255a2d..701e8ac 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -106,7 +106,7 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): source_bytes = loader.get_data(file) try: code = loader.source_to_code(source_bytes, dfile or file, - _optimize=optimize) + _optimize=optimize) except Exception as err: py_exc = PyCompileError(err.__class__, err, dfile or file) if doraise: @@ -121,11 +121,13 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): except FileExistsError: pass source_stats = loader.path_stats(file) - bytecode = importlib._bootstrap._code_to_bytecode(code, - source_stats['mtime'], len(source_bytes)) - loader._cache_bytecode(file, cfile, bytecode) + bytecode = importlib._bootstrap._code_to_bytecode( + code, source_stats['mtime'], source_stats['size']) + mode = importlib._bootstrap._calc_mode(file) + importlib._bootstrap._write_atomic(cfile, bytecode, mode) return cfile + def main(args=None): """Compile several source files. diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index f3c1a6a..13947b1 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -2,6 +2,7 @@ import imp import os import py_compile import shutil +import stat import tempfile import unittest @@ -54,8 +55,18 @@ class PyCompileTests(unittest.TestCase): self.assertTrue(os.path.exists(self.pyc_path)) self.assertFalse(os.path.exists(self.cache_path)) -def test_main(): - support.run_unittest(PyCompileTests) + 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) + if __name__ == "__main__": - test_main() + unittest.main()
\ No newline at end of file |