Created
August 3, 2008 01:36
-
-
Save codeslinger/3792 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim:set ts=4 sw=4 et ai: | |
from __future__ import with_statement | |
""" | |
:Author: Toby DiPasquale <[email protected]> | |
:Copyright: Copyright (c) 2008 Toby DiPasquale. Free for use for any purpose | |
by anyone forever. | |
Introduction | |
============ | |
Built from the recommendations found in the "Eat My Data" talk by Stewart | |
Smith of MySQL AB (online here: http://www.flamingspork.com/talks/), this | |
module will help you avoid data corruption issues on multiple platforms. | |
This module requires Python 2.5 or higher. | |
""" | |
__docformat__ = "restructuredtext" | |
import sys | |
import os | |
# | |
# Mac OS X's fsync() doesn't really sync to disk; instead we have | |
# to issue this fcntl() to make sure the data is on disk on that | |
# platform. | |
# | |
if sys.platform == 'darwin': | |
# 51 == F_FULLSYNC on Mac OS X (/usr/include/sys/fcntl.h) | |
import fcntl | |
_sync = lambda fd : fcntl.fcntl(fd, 51) | |
else: | |
_sync = os.fsync | |
def save(path, data, mode='w', offset=None, whence=os.SEEK_SET): | |
""" | |
Write `data` into `path` in the safest way possible vis a vis avoiding | |
data corruption. | |
:Parameters: | |
path : str | |
path to file into which to write `data` | |
data : str | |
contents to write to `path` | |
mode : str | |
mode with which to open `path` (e.g. ``'w'`` for writing, ``'a'`` | |
for appending, etc.; see `open` docs for details) | |
offset : long | |
byte offset into `path` into which to write `data` | |
whence : int | |
how to interpret `offset` in terms of positioning in the file; | |
see `os.seek` for details on valid arguments | |
:raise `OSError`: raised by underlying OS ops in case of error | |
:raise `IOError`: raised by underlying file ops in case of error | |
""" | |
tmp = _tempfile(path) | |
with open(tmp, mode) as f: | |
if offset: | |
f.seek(offset, whence) | |
f.write(data) | |
f.flush() | |
_sync(f.fileno()) | |
os.rename(tmp, path) | |
def _tempfile(path): | |
""" | |
Create a tempfile name for the given `path`. | |
:Parameters: | |
path : str | |
original file path | |
:rtype: str | |
:return: path to tempfile for `path` | |
""" | |
return '%s.tmp' % path |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment