mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-02-25 10:00:48 +01:00
Added makeBackupIfSmaller and Everything and Nothing.
This commit is contained in:
parent
e98bb7a787
commit
5dbcf950a8
42
src/utils.py
42
src/utils.py
@ -707,12 +707,13 @@ def mungeEmailForWeb(s):
|
|||||||
class AtomicFile(file):
|
class AtomicFile(file):
|
||||||
"""Used for files that need to be atomically written -- i.e., if there's a
|
"""Used for files that need to be atomically written -- i.e., if there's a
|
||||||
failure, the original file remains, unmodified. mode must be 'w' or 'wb'"""
|
failure, the original file remains, unmodified. mode must be 'w' or 'wb'"""
|
||||||
def __init__(self, filename, mode='w',
|
def __init__(self, filename, mode='w', allowEmptyOverwrite=True,
|
||||||
allowEmptyOverwrite=True, tmpDir=None):
|
makeBackupIfSmaller=True, tmpDir=None):
|
||||||
if mode not in ('w', 'wb'):
|
if mode not in ('w', 'wb'):
|
||||||
raise ValueError, 'Invalid mode: %r' % mode
|
raise ValueError, 'Invalid mode: %r' % mode
|
||||||
self.rolledback = False
|
self.rolledback = False
|
||||||
self.allowEmptyOverwrite = allowEmptyOverwrite
|
self.allowEmptyOverwrite = allowEmptyOverwrite
|
||||||
|
self.makeBackupIfSmaller = makeBackupIfSmaller
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
if tmpDir is None:
|
if tmpDir is None:
|
||||||
# If not given a tmpDir, we'll just put a random token on the end
|
# If not given a tmpDir, we'll just put a random token on the end
|
||||||
@ -723,6 +724,8 @@ class AtomicFile(file):
|
|||||||
# directory), put our random token on the end, and put it in tmpDir
|
# directory), put our random token on the end, and put it in tmpDir
|
||||||
tempFilename = '%s.%s' % (os.path.basename(self.filename), mktemp())
|
tempFilename = '%s.%s' % (os.path.basename(self.filename), mktemp())
|
||||||
self.tempFilename = os.path.join(tmpDir, tempFilename)
|
self.tempFilename = os.path.join(tmpDir, tempFilename)
|
||||||
|
# This doesn't work because of the uncollectable garbage effect.
|
||||||
|
# self.__parent = super(AtomicFile, self)
|
||||||
super(AtomicFile, self).__init__(self.tempFilename, mode)
|
super(AtomicFile, self).__init__(self.tempFilename, mode)
|
||||||
|
|
||||||
def rollback(self):
|
def rollback(self):
|
||||||
@ -739,13 +742,20 @@ class AtomicFile(file):
|
|||||||
# doesn't exist.
|
# doesn't exist.
|
||||||
size = os.path.getsize(self.tempFilename)
|
size = os.path.getsize(self.tempFilename)
|
||||||
originalExists = os.path.exists(self.filename)
|
originalExists = os.path.exists(self.filename)
|
||||||
|
# We use shutil.move here instead of os.rename because
|
||||||
|
# the latter doesn't work on Windows when self.filename
|
||||||
|
# (the target) already exists. shutil.move handles those
|
||||||
|
# intricacies for us.
|
||||||
if size or self.allowEmptyOverwrite or not originalExists:
|
if size or self.allowEmptyOverwrite or not originalExists:
|
||||||
if os.path.exists(self.tempFilename):
|
if originalExists:
|
||||||
# We use shutil.move here instead of os.rename because
|
currentSize = os.path.getsize(self.filename)
|
||||||
# the latter doesn't work on Windows when self.filename
|
if self.makeBackupIfSmaller and size < currentSize:
|
||||||
# (the target) already exists. shutil.move handles those
|
now = int(time.time())
|
||||||
# intricacies for us.
|
backupFilename = '%s.backup.%s' % (self.filename, now)
|
||||||
shutil.move(self.tempFilename, self.filename)
|
shutil.copy(self.filename, backupFilename)
|
||||||
|
shutil.move(self.tempFilename, self.filename)
|
||||||
|
else:
|
||||||
|
raise ValueError, 'AtomicFile.close called after rollback.'
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
# We rollback because if we're deleted without being explicitly closed,
|
# We rollback because if we're deleted without being explicitly closed,
|
||||||
@ -787,6 +797,22 @@ def callTracer(fd=None, basename=True):
|
|||||||
print >>fd, '%s: %s(%s)' % (filename, funcname, lineno)
|
print >>fd, '%s: %s(%s)' % (filename, funcname, lineno)
|
||||||
return tracer
|
return tracer
|
||||||
|
|
||||||
|
|
||||||
|
# These are used by Owner and Misc for their callBefore/callAfter attributes.
|
||||||
|
class Everything(object):
|
||||||
|
def __contains__(self, x):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter([])
|
||||||
|
|
||||||
|
class Nothing(object):
|
||||||
|
def __contains__(self, x):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter([])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod(sys.modules['__main__'])
|
doctest.testmod(sys.modules['__main__'])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user