diff options
author | Brett Cannon <brett@python.org> | 2013-06-14 22:33:00 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2013-06-14 22:33:00 (GMT) |
commit | 33915eba7c8293eab4962345fbbb1e5d193295ed (patch) | |
tree | 320c366c8c8f651c6c0d515b662f8cecf2e41cac /Lib | |
parent | 3fe35e65034de82c45e2d8fe1ebe4a2929c68453 (diff) | |
download | cpython-33915eba7c8293eab4962345fbbb1e5d193295ed.zip cpython-33915eba7c8293eab4962345fbbb1e5d193295ed.tar.gz cpython-33915eba7c8293eab4962345fbbb1e5d193295ed.tar.bz2 |
Issue #17222: Raise FileExistsError when py_compile.compile would
overwrite a symlink or non-regular file with a regular file.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/py_compile.py | 14 | ||||
-rw-r--r-- | Lib/test/test_py_compile.py | 20 |
2 files changed, 34 insertions, 0 deletions
diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 701e8ac..cee35a5 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -7,6 +7,7 @@ import imp import importlib._bootstrap import importlib.machinery import os +import os.path import sys import traceback @@ -96,12 +97,25 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): See compileall.py for a script/module that uses this module to byte-compile all installed files (or all files in selected directories). + + Do note that FileExistsError is raised if cfile ends up pointing at a + non-regular file or symlink. Because the compilation uses a file renaming, + the resulting file would be regular and thus not the same type of file as + it was previously. """ if cfile is None: if optimize >= 0: cfile = imp.cache_from_source(file, debug_override=not optimize) else: cfile = imp.cache_from_source(file) + if os.path.islink(cfile): + msg = ('{} is a symlink and will be changed into a regular file if ' + 'import writes a byte-compiled file to it') + raise FileExistsError(msg.format(file, cfile)) + elif os.path.exists(cfile) and not os.path.isfile(cfile): + msg = ('{} is a non-regular file and will be changed into a regular ' + 'one if import writes a byte-compiled file to it') + raise FileExistsError(msg.format(file, cfile)) loader = importlib.machinery.SourceFileLoader('<py_compile>', file) source_bytes = loader.get_data(file) try: diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index e179554..54dc596 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -36,6 +36,26 @@ class PyCompileTests(unittest.TestCase): 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 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)) |