X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=lib%2Fbup%2Fcompat.py;h=00575036e27cc46f7fb6b3408e273831526b9daa;hb=4448f184253125e1b8bd0c55d0098a335d15b90b;hp=9002025a6d49ec76cda219bc46468f10769ca905;hpb=ca1b82ee3ab053c50fc7c1fc491928c5c2c8fc19;p=bup.git diff --git a/lib/bup/compat.py b/lib/bup/compat.py index 9002025..0057503 100644 --- a/lib/bup/compat.py +++ b/lib/bup/compat.py @@ -13,6 +13,7 @@ py3 = py_maj >= 3 if py3: # pylint: disable=unused-import + from contextlib import ExitStack, nullcontext from os import environb as environ from os import fsdecode, fsencode from shlex import quote @@ -46,13 +47,17 @@ if py3: """ def __init__(self, ex, rethrow=True): + self.closed = False self.ex = ex self.rethrow = rethrow def __enter__(self): return None def __exit__(self, exc_type, exc_value, traceback): + self.closed = True if not exc_type and self.ex and self.rethrow: raise self.ex + def __del__(self): + assert self.closed def items(x): return x.items() @@ -82,6 +87,8 @@ if py3: else: # Python 2 + from contextlib import contextmanager + ModuleNotFoundError = ImportError def fsdecode(x): @@ -97,6 +104,10 @@ else: # Python 2 # pylint: disable=unused-import from bup.py2raise import reraise + @contextmanager + def nullcontext(enter_result=None): + yield enter_result + # on py3 this causes errors, obviously # pylint: disable=undefined-variable input = raw_input @@ -137,12 +148,14 @@ else: # Python 2 """ def __init__(self, ex, rethrow=True): + self.closed = False self.ex = ex self.rethrow = rethrow def __enter__(self): if self.ex: add_ex_tb(self.ex) def __exit__(self, exc_type, exc_value, traceback): + self.closed = True if exc_value: if self.ex: add_ex_tb(exc_value) @@ -150,6 +163,8 @@ else: # Python 2 return if self.rethrow and self.ex: raise self.ex + def __del__(self): + assert self.closed def dump_traceback(ex): stack = [ex] @@ -167,6 +182,31 @@ else: # Python 2 tb = getattr(ex, '__traceback__', None) print_exception(type(ex), ex, tb) + class ExitStack: + def __init__(self): + self.contexts = [] + + def __enter__(self): + return self + + def __exit__(self, value_type, value, traceback): + init_value = value + for ctx in reversed(self.contexts): + try: + ctx.__exit__(value_type, value, traceback) + except BaseException as ex: + add_ex_tb(ex) + if value: + add_ex_ctx(ex, value) + value_type = type(ex) + value = ex + traceback = ex.__traceback__ + if value is not init_value: + raise value + + def enter_context(self, x): + self.contexts.append(x) + def items(x): return x.iteritems()