mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-01 00:45:52 +00:00
zfec: pyutil: make temp directories more convenient to use and more likely to clean up properly on Windows
This commit is contained in:
parent
eb8709802d
commit
9103430791
@ -66,16 +66,63 @@ def remove(f, tries=4, basedelay=0.1):
|
|||||||
basedelay *= 2
|
basedelay *= 2
|
||||||
return os.remove(f) # The last try.
|
return os.remove(f) # The last try.
|
||||||
|
|
||||||
class NamedTemporaryDirectory:
|
class _Dir(object):
|
||||||
"""
|
"""
|
||||||
This calls tempfile.mkdtemp(), stores the name of the dir in
|
Hold a set of files and subdirs and clean them all up when asked to.
|
||||||
self.name, and rmrf's the dir when it gets garbage collected or
|
|
||||||
"shutdown()".
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, cleanup=True, *args, **kwargs):
|
def __init__(self, name, cleanup=True):
|
||||||
""" If cleanup, then the directory will be rmrf'ed when the object is shutdown. """
|
self.name = name
|
||||||
self.cleanup = cleanup
|
self.cleanup = cleanup
|
||||||
self.name = tempfile.mkdtemp(*args, **kwargs)
|
self.files = set()
|
||||||
|
self.subdirs = set()
|
||||||
|
|
||||||
|
def file(self, fname, mode=None):
|
||||||
|
"""
|
||||||
|
Create a file in the tempdir and remember it so as to close() it
|
||||||
|
before attempting to cleanup the temp dir.
|
||||||
|
|
||||||
|
@rtype: file
|
||||||
|
"""
|
||||||
|
ffn = os.path.join(self.name, fname)
|
||||||
|
if mode is not None:
|
||||||
|
fo = open(ffn, mode)
|
||||||
|
else:
|
||||||
|
fo = open(ffn)
|
||||||
|
self.register_file(fo)
|
||||||
|
return fo
|
||||||
|
|
||||||
|
def subdir(self, dirname):
|
||||||
|
"""
|
||||||
|
Create a subdirectory in the tempdir and remember it so as to call
|
||||||
|
shutdown() on it before attempting to clean up.
|
||||||
|
|
||||||
|
@rtype: NamedTemporaryDirectory instance
|
||||||
|
"""
|
||||||
|
ffn = os.path.join(self.name, dirname)
|
||||||
|
sd = _Dir(ffn, self.cleanup)
|
||||||
|
self.register_subdir(sd)
|
||||||
|
|
||||||
|
def register_file(self, fileobj):
|
||||||
|
"""
|
||||||
|
Remember the file object and call close() on it before attempting to
|
||||||
|
clean up.
|
||||||
|
"""
|
||||||
|
self.files.add(fileobj)
|
||||||
|
|
||||||
|
def register_subdir(self, dirobj):
|
||||||
|
"""
|
||||||
|
Remember the _Dir object and call shutdown() on it before attempting
|
||||||
|
to clean up.
|
||||||
|
"""
|
||||||
|
self.subdirs.add(dirobj)
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
if self.cleanup and hasattr(self, 'name'):
|
||||||
|
for subdir in self.subdirs:
|
||||||
|
subdir.shutdown()
|
||||||
|
for fileobj in self.files:
|
||||||
|
fileobj.close() # "close()" is idempotent so we don't need to catch exceptions here
|
||||||
|
rm_dir(self.name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s instance at %x %s>" % (self.__class__.__name__, id(self), self.name)
|
return "<%s instance at %x %s>" % (self.__class__.__name__, id(self), self.name)
|
||||||
@ -90,9 +137,21 @@ class NamedTemporaryDirectory:
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def shutdown(self):
|
class NamedTemporaryDirectory(_Dir):
|
||||||
if self.cleanup and hasattr(self, 'name'):
|
"""
|
||||||
rm_dir(self.name)
|
Call tempfile.mkdtemp(), store the name of the dir in self.name, and
|
||||||
|
rm_dir() when it gets garbage collected or "shutdown()".
|
||||||
|
|
||||||
|
Also optionally keep track of file objects for files within the tempdir
|
||||||
|
and call close() on them before rm_dir(). This is a convenient way to
|
||||||
|
open temp files within the directory, and it is very helpful on Windows
|
||||||
|
because you can't delete a directory which contains a file which is
|
||||||
|
currently open.
|
||||||
|
"""
|
||||||
|
def __init__(self, cleanup=True, *args, **kwargs):
|
||||||
|
""" If cleanup, then the directory will be rmrf'ed when the object is shutdown. """
|
||||||
|
name = tempfile.mkdtemp(*args, **kwargs)
|
||||||
|
_Dir.__init__(self, name, cleanup)
|
||||||
|
|
||||||
def make_dirs(dirname, mode=0777, strictmode=False):
|
def make_dirs(dirname, mode=0777, strictmode=False):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user