summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Kreen2012-06-15 13:32:06 +0000
committerMarko Kreen2012-06-15 13:32:06 +0000
commitc51a6dc989a9882cb91bbfe2927cd3cedb2d506a (patch)
tree018fd920cc4f41d602bba6eced4313098f28ed5a
parent8b4c4cd42abab87181c46802945078ffd8ab2e21 (diff)
skytools.fileutil: new module, contains write_atomic()
-rw-r--r--python/skytools/__init__.py2
-rw-r--r--python/skytools/fileutil.py37
2 files changed, 39 insertions, 0 deletions
diff --git a/python/skytools/__init__.py b/python/skytools/__init__.py
index 6bdeb51e..4f6d1bde 100644
--- a/python/skytools/__init__.py
+++ b/python/skytools/__init__.py
@@ -29,6 +29,8 @@ _symbols = {
'T_SEQUENCE': 'skytools.dbstruct:T_SEQUENCE',
'T_TABLE': 'skytools.dbstruct:T_TABLE',
'T_TRIGGER': 'skytools.dbstruct:T_TRIGGER',
+ # skytools.fileutil
+ 'write_atomic': 'skytools.fileutil:write_atomic',
# skytools.gzlog
'gzip_append': 'skytools.gzlog:gzip_append',
# skytools.parsing
diff --git a/python/skytools/fileutil.py b/python/skytools/fileutil.py
new file mode 100644
index 00000000..fd657fd4
--- /dev/null
+++ b/python/skytools/fileutil.py
@@ -0,0 +1,37 @@
+"""File utilities"""
+
+import os
+
+__all__ = ['write_atomic']
+
+def write_atomic(fn, data, bakext=None, mode='b'):
+ """Write file with rename."""
+
+ if mode not in ['', 'b', 't']:
+ raise ValueError("unsupported fopen mode")
+
+ # write new data to tmp file
+ fn2 = fn + '.new'
+ f = open(fn2, 'w' + mode)
+ f.write(data)
+ f.close()
+
+ # link old data to bak file
+ if bakext:
+ if bakext.find('/') >= 0:
+ raise ValueError("invalid bakext")
+ fnb = fn + bakext
+ try:
+ os.unlink(fnb)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ try:
+ os.link(fn, fnb)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ # atomically replace file
+ os.rename(fn2, fn)
+