| 
 | 1 | +import errno  | 
 | 2 | +import os  | 
 | 3 | +import random  | 
 | 4 | +import shutil  | 
 | 5 | + | 
 | 6 | +_ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"  | 
 | 7 | + | 
 | 8 | + | 
 | 9 | +def _get_candidate_name(size=8):  | 
 | 10 | + return "".join(random.choice(_ascii_letters) for _ in range(size))  | 
 | 11 | + | 
 | 12 | + | 
 | 13 | +def _sanitize_inputs(suffix, prefix, dir):  | 
 | 14 | + if dir is None:  | 
 | 15 | + dir = "/tmp"  | 
 | 16 | + if suffix is None:  | 
 | 17 | + suffix = ""  | 
 | 18 | + if prefix is None:  | 
 | 19 | + prefix = ""  | 
 | 20 | + return suffix, prefix, dir  | 
 | 21 | + | 
 | 22 | + | 
 | 23 | +def _try(action, *args, **kwargs):  | 
 | 24 | + try:  | 
 | 25 | + action(*args, **kwargs)  | 
 | 26 | + return True  | 
 | 27 | + except OSError as e:  | 
 | 28 | + if e.errno != errno.EEXIST:  | 
 | 29 | + raise e  | 
 | 30 | + return False  | 
 | 31 | + | 
 | 32 | + | 
 | 33 | +def mkdtemp(suffix=None, prefix=None, dir=None):  | 
 | 34 | + suffix, prefix, dir = _sanitize_inputs(suffix, prefix, dir)  | 
 | 35 | + | 
 | 36 | + _try(os.mkdir, dir)  | 
 | 37 | + | 
 | 38 | + while True:  | 
 | 39 | + name = _get_candidate_name()  | 
 | 40 | + file = os.path.join(dir, prefix + name + suffix)  | 
 | 41 | + if _try(os.mkdir, file):  | 
 | 42 | + return file  | 
 | 43 | + | 
 | 44 | + | 
 | 45 | +class TemporaryDirectory:  | 
 | 46 | + def __init__(self, suffix=None, prefix=None, dir=None):  | 
 | 47 | + self.name = mkdtemp(suffix, prefix, dir)  | 
 | 48 | + | 
 | 49 | + def __repr__(self):  | 
 | 50 | + return "<{} {!r}>".format(self.__class__.__name__, self.name)  | 
 | 51 | + | 
 | 52 | + def __enter__(self):  | 
 | 53 | + return self.name  | 
 | 54 | + | 
 | 55 | + def __exit__(self, exc, value, tb):  | 
 | 56 | + self.cleanup()  | 
 | 57 | + | 
 | 58 | + def cleanup(self):  | 
 | 59 | + _try(shutil.rmtree, self.name)  | 
0 commit comments