Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 34937ce

Browse files
committed
Issue #6074: Forward port Windows read-only source file fix from 2.7
1 parent 2d51f68 commit 34937ce

3 files changed

Lines changed: 60 additions & 5 deletions

File tree

Lib/test/test_import.py

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,24 @@
2020
from test import script_helper
2121

2222

23-
def remove_files(name):
24-
for f in (name + ".py",
25-
name + ".pyc",
26-
name + ".pyo",
27-
name + ".pyw",
23+
def _iter_files(name):
24+
for f in (name + os.extsep + "py",
25+
name + os.extsep + "pyc",
26+
name + os.extsep + "pyo",
27+
name + os.extsep + "pyw",
2828
name + "$py.class"):
29+
yield f
30+
31+
def chmod_files(name):
32+
for f in _iter_files(name):
33+
try:
34+
os.chmod(f, 0o600)
35+
except OSError as exc:
36+
if exc.errno != errno.ENOENT:
37+
raise
38+
39+
def remove_files(name):
40+
for f in _iter_files(name):
2941
unlink(f)
3042
rmtree('__pycache__')
3143

@@ -122,6 +134,40 @@ def test_execute_bit_not_copied(self):
122134
remove_files(TESTFN)
123135
unload(TESTFN)
124136

137+
def test_rewrite_pyc_with_read_only_source(self):
138+
# Issue 6074: a long time ago on posix, and more recently on Windows,
139+
# a read only source file resulted in a read only pyc file, which
140+
# led to problems with updating it later
141+
sys.path.insert(0, os.curdir)
142+
fname = TESTFN + os.extsep + "py"
143+
try:
144+
# Write a Python file, make it read-only and import it
145+
with open(fname, 'w') as f:
146+
f.write("x = 'original'\n")
147+
# Tweak the mtime of the source to ensure pyc gets updated later
148+
s = os.stat(fname)
149+
os.utime(fname, (s.st_atime, s.st_mtime-100000000))
150+
os.chmod(fname, 0o400)
151+
m1 = __import__(TESTFN)
152+
self.assertEqual(m1.x, 'original')
153+
# Change the file and then reimport it
154+
os.chmod(fname, 0o600)
155+
with open(fname, 'w') as f:
156+
f.write("x = 'rewritten'\n")
157+
unload(TESTFN)
158+
m2 = __import__(TESTFN)
159+
self.assertEqual(m2.x, 'rewritten')
160+
# Now delete the source file and check the pyc was rewritten
161+
unlink(TESTFN)
162+
unload(TESTFN)
163+
m3 = __import__(TESTFN)
164+
self.assertEqual(m3.x, 'rewritten')
165+
finally:
166+
chmod_files(TESTFN)
167+
remove_files(TESTFN)
168+
unload(TESTFN)
169+
del sys.path[0]
170+
125171
def test_imp_module(self):
126172
# Verify that the imp module can correctly load and find .py files
127173
# XXX (ncoghlan): It would be nice to use support.CleanImport

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.2.4
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #6074: Ensure cached bytecode files can always be updated by the
14+
user that created them, even when the source file is read-only.
15+
1316
- Issue #14783: Improve int() docstring and switch docstrings for str(),
1417
range(), and slice() to use multi-line signatures.
1518

Python/import.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,12 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
11741174
time_t mtime = srcstat->st_mtime;
11751175
#ifdef MS_WINDOWS /* since Windows uses different permissions */
11761176
mode_t mode = srcstat->st_mode & ~S_IEXEC;
1177+
/* Issue #6074: We ensure user write access, so we can delete it later
1178+
* when the source file changes. (On POSIX, this only requires write
1179+
* access to the directory, on Windows, we need write access to the file
1180+
* as well)
1181+
*/
1182+
mode |= _S_IWRITE;
11771183
#else
11781184
mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH;
11791185
mode_t dirmode = (srcstat->st_mode |

0 commit comments

Comments
 (0)