X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=bup.git;a=blobdiff_plain;f=lib%2Fbup%2Fio.py;h=a384f1007e5d5f0452d646633a658b01b1dad9f0;hp=512d36434ed57e800f3b1f647a8982a909ec6ac2;hb=4448f184253125e1b8bd0c55d0098a335d15b90b;hpb=aeffdb776ded3ae2a95f1a216fdcbcb7dc2dc8f2 diff --git a/lib/bup/io.py b/lib/bup/io.py index 512d364..a384f10 100644 --- a/lib/bup/io.py +++ b/lib/bup/io.py @@ -1,7 +1,9 @@ from __future__ import absolute_import, print_function +import mmap as py_mmap from bup import compat +from bup.compat import pending_raise if compat.py_maj > 2: @@ -20,3 +22,47 @@ else: """Return a string representation of a path.""" # FIXME: configurability (might git-config quotePath be involved?) return x + + +assert not hasattr(py_mmap.mmap, '__del__') +if hasattr(py_mmap.mmap, '__enter__'): + assert hasattr(py_mmap.mmap, '__exit__') + +class mmap(py_mmap.mmap): + '''mmap.mmap wrapper that detects and complains about any instances + that aren't explicitly closed. + + ''' + + def __init__(self, *args, **kwargs): + self._bup_closed = True + # Silence deprecation warnings. mmap's current parent is + # object, which accepts no params and as of at least 2.7 + # warns about them. + if py_mmap.mmap.__init__ is not object.__init__: + super(mmap, self).__init__(self, *args, **kwargs) + self._bup_closed = False + + def close(self): + self._bup_closed = True + super(mmap, self).close() + + if hasattr(py_mmap.mmap, '__enter__'): + def __enter__(self): + super(mmap, self).__enter__() + return self + def __exit__(self, type, value, traceback): + # Don't call self.close() when the parent has its own __exit__; + # defer to it. + self._bup_closed = True + result = super(mmap, self).__exit__(type, value, traceback) + return result + else: + def __enter__(self): + return self + def __exit__(self, type, value, traceback): + with pending_raise(value, rethrow=False): + self.close() + + def __del__(self): + assert self._bup_closed