mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-27 13:19:24 +01:00
Added makeBackupIfSmaller and Everything and Nothing.
This commit is contained in:
parent
e98bb7a787
commit
5dbcf950a8
34
src/utils.py
34
src/utils.py
@ -707,12 +707,13 @@ def mungeEmailForWeb(s):
|
||||
class AtomicFile(file):
|
||||
"""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'"""
|
||||
def __init__(self, filename, mode='w',
|
||||
allowEmptyOverwrite=True, tmpDir=None):
|
||||
def __init__(self, filename, mode='w', allowEmptyOverwrite=True,
|
||||
makeBackupIfSmaller=True, tmpDir=None):
|
||||
if mode not in ('w', 'wb'):
|
||||
raise ValueError, 'Invalid mode: %r' % mode
|
||||
self.rolledback = False
|
||||
self.allowEmptyOverwrite = allowEmptyOverwrite
|
||||
self.makeBackupIfSmaller = makeBackupIfSmaller
|
||||
self.filename = filename
|
||||
if tmpDir is None:
|
||||
# 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
|
||||
tempFilename = '%s.%s' % (os.path.basename(self.filename), mktemp())
|
||||
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)
|
||||
|
||||
def rollback(self):
|
||||
@ -739,13 +742,20 @@ class AtomicFile(file):
|
||||
# doesn't exist.
|
||||
size = os.path.getsize(self.tempFilename)
|
||||
originalExists = os.path.exists(self.filename)
|
||||
if size or self.allowEmptyOverwrite or not originalExists:
|
||||
if os.path.exists(self.tempFilename):
|
||||
# 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 originalExists:
|
||||
currentSize = os.path.getsize(self.filename)
|
||||
if self.makeBackupIfSmaller and size < currentSize:
|
||||
now = int(time.time())
|
||||
backupFilename = '%s.backup.%s' % (self.filename, now)
|
||||
shutil.copy(self.filename, backupFilename)
|
||||
shutil.move(self.tempFilename, self.filename)
|
||||
else:
|
||||
raise ValueError, 'AtomicFile.close called after rollback.'
|
||||
|
||||
def __del__(self):
|
||||
# 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)
|
||||
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__':
|
||||
import doctest
|
||||
doctest.testmod(sys.modules['__main__'])
|
||||
|
Loading…
Reference in New Issue
Block a user