Issue #17244: Don't mask exceptions raised during the creation of
bytecode files in py_compile. Thanks to Arfrever Frehtes Taifersar Arahesis for the bug report.
This commit is contained in:
parent
672559fc4f
commit
edfd6ae79c
|
@ -474,6 +474,18 @@ def _get_sourcefile(bytecode_path):
|
||||||
return source_path if _path_isfile(source_stats) else 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):
|
def _verbose_message(message, *args, verbosity=1):
|
||||||
"""Print the message to stderr if -v/PYTHONVERBOSE is turned on."""
|
"""Print the message to stderr if -v/PYTHONVERBOSE is turned on."""
|
||||||
if sys.flags.verbose >= verbosity:
|
if sys.flags.verbose >= verbosity:
|
||||||
|
@ -1060,13 +1072,7 @@ class SourceFileLoader(FileLoader, SourceLoader):
|
||||||
|
|
||||||
def _cache_bytecode(self, source_path, bytecode_path, data):
|
def _cache_bytecode(self, source_path, bytecode_path, data):
|
||||||
# Adapt between the two APIs
|
# Adapt between the two APIs
|
||||||
try:
|
mode = _calc_mode(source_path)
|
||||||
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
|
|
||||||
return self.set_data(bytecode_path, data, _mode=mode)
|
return self.set_data(bytecode_path, data, _mode=mode)
|
||||||
|
|
||||||
def set_data(self, path, data, *, _mode=0o666):
|
def set_data(self, path, data, *, _mode=0o666):
|
||||||
|
|
|
@ -106,7 +106,7 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1):
|
||||||
source_bytes = loader.get_data(file)
|
source_bytes = loader.get_data(file)
|
||||||
try:
|
try:
|
||||||
code = loader.source_to_code(source_bytes, dfile or file,
|
code = loader.source_to_code(source_bytes, dfile or file,
|
||||||
_optimize=optimize)
|
_optimize=optimize)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
py_exc = PyCompileError(err.__class__, err, dfile or file)
|
py_exc = PyCompileError(err.__class__, err, dfile or file)
|
||||||
if doraise:
|
if doraise:
|
||||||
|
@ -121,11 +121,13 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1):
|
||||||
except FileExistsError:
|
except FileExistsError:
|
||||||
pass
|
pass
|
||||||
source_stats = loader.path_stats(file)
|
source_stats = loader.path_stats(file)
|
||||||
bytecode = importlib._bootstrap._code_to_bytecode(code,
|
bytecode = importlib._bootstrap._code_to_bytecode(
|
||||||
source_stats['mtime'], len(source_bytes))
|
code, source_stats['mtime'], source_stats['size'])
|
||||||
loader._cache_bytecode(file, cfile, bytecode)
|
mode = importlib._bootstrap._calc_mode(file)
|
||||||
|
importlib._bootstrap._write_atomic(cfile, bytecode, mode)
|
||||||
return cfile
|
return cfile
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
"""Compile several source files.
|
"""Compile several source files.
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import imp
|
||||||
import os
|
import os
|
||||||
import py_compile
|
import py_compile
|
||||||
import shutil
|
import shutil
|
||||||
|
import stat
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -54,8 +55,18 @@ class PyCompileTests(unittest.TestCase):
|
||||||
self.assertTrue(os.path.exists(self.pyc_path))
|
self.assertTrue(os.path.exists(self.pyc_path))
|
||||||
self.assertFalse(os.path.exists(self.cache_path))
|
self.assertFalse(os.path.exists(self.cache_path))
|
||||||
|
|
||||||
def test_main():
|
def test_exceptions_propagate(self):
|
||||||
support.run_unittest(PyCompileTests)
|
# 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__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
unittest.main()
|
6980
Python/importlib.h
6980
Python/importlib.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue