diff options
author | Will McGugan <willmcgugan@gmail.com> | 2015-04-24 11:53:08 +0100 |
---|---|---|
committer | Will McGugan <willmcgugan@gmail.com> | 2015-04-24 11:53:08 +0100 |
commit | dd541bc85a24f04c537358767836e781e9ac285b (patch) | |
tree | fdd823f6eb21d827225004d1788c8518b1d9bfca | |
parent | ce1d5dd3afa6661439d2ad5efbd05325720ffb30 (diff) | |
parent | 97c367eb6b47d6b03d6b560d65f6622d0f7e810e (diff) | |
download | pyfilesystem-git-dd541bc85a24f04c537358767836e781e9ac285b.tar.gz |
Merge branch 'master' of github.com:PyFilesystem/pyfilesystem
-rw-r--r-- | .gitignore | 12 | ||||
-rw-r--r-- | fs/utils.py | 44 |
2 files changed, 55 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89ad3c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.orig +*.project +*.pyc +*.egg +*.egg-info +*.db +*.sqlite +*.sublime-* +/**/__*__ +.eggs +.tox +build/ diff --git a/fs/utils.py b/fs/utils.py index 8fd6254..208fc61 100644 --- a/fs/utils.py +++ b/fs/utils.py @@ -16,8 +16,10 @@ __all__ = ['copyfile', 'isfile', 'isdir', 'find_duplicates', - 'print_fs'] + 'print_fs', + 'open_atomic_write'] +import os import sys import stat import six @@ -628,6 +630,46 @@ def print_fs(fs, return dircount[0], filecount[0] +class AtomicWriter(object): + """Context manager to perform atomic writes""" + + def __init__(self, fs, path, mode='w'): + self.fs = fs + self.path = path + self.mode = mode + self.tmp_path = path + '~' + self._f = None + + def __enter__(self): + self._f = self.fs.open(self.tmp_path, self.mode) + return self._f + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + if self._f is not None: + if hasattr('_f', 'flush'): + self._f.flush() + if hasattr(self._f, 'fileno'): + os.fsync(self._f.fileno()) + self._f.close() + self._f = None + self.fs.rename(self.tmp_path, self.path) + else: + if self._f is not None: + self._f.close() + + +def open_atomic_write(fs, path, mode='w'): + """Open a file for 'atomic' writing + + This returns a context manager which ensures that a file is written in its entirety or not at all. + + """ + return AtomicWriter(fs, path, mode=mode) + + + + if __name__ == "__main__": from fs.tempfs import TempFS from six import b |