summaryrefslogtreecommitdiffstats
path: root/Lib/importlib
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-10-17 17:28:44 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-10-17 17:28:44 (GMT)
commit707033a694ec6503bf670f1faf0db3bc69897d35 (patch)
treea88fe547a4b614cb4aaea0621f202dd8556c1d85 /Lib/importlib
parent5b9f4c1539aee9107e4958eaa50ab205fd6a72e4 (diff)
downloadcpython-707033a694ec6503bf670f1faf0db3bc69897d35.zip
cpython-707033a694ec6503bf670f1faf0db3bc69897d35.tar.gz
cpython-707033a694ec6503bf670f1faf0db3bc69897d35.tar.bz2
Issue #13146: Writing a pyc file is now atomic under POSIX.
Diffstat (limited to 'Lib/importlib')
-rw-r--r--Lib/importlib/_bootstrap.py26
1 files changed, 23 insertions, 3 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 18ea85c..824a31c 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -80,6 +80,27 @@ def _path_absolute(path):
return _path_join(_os.getcwd(), path)
+def _write_atomic(path, data):
+ """Best-effort function to write data to a path atomically."""
+ if not sys.platform.startswith('win'):
+ # On POSIX-like platforms, renaming is atomic
+ path_tmp = path + '.tmp'
+ try:
+ fd = _os.open(path_tmp, _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY)
+ with _io.FileIO(fd, 'wb') as file:
+ file.write(data)
+ _os.rename(path_tmp, path)
+ except OSError:
+ try:
+ _os.unlink(path_tmp)
+ except OSError:
+ pass
+ raise
+ else:
+ with _io.FileIO(path, 'wb') as file:
+ file.write(data)
+
+
def _wrap(new, old):
"""Simple substitute for functools.wraps."""
for replace in ['__module__', '__name__', '__doc__']:
@@ -494,9 +515,8 @@ class _SourceFileLoader(_FileLoader, SourceLoader):
else:
raise
try:
- with _io.FileIO(path, 'wb') as file:
- file.write(data)
- except IOError as exc:
+ _write_atomic(path, data)
+ except OSError as exc:
# Don't worry if you can't write bytecode.
if exc.errno == errno.EACCES:
return