]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/io.py
Update base_version to 0.34~ for 0.34 development
[bup.git] / lib / bup / io.py
index 571e9b9102d76fa43b42c7fb283d722b17b0f618..e2fd410b3eb8b1eb444118acf06a8f8e88a8f62c 100644 (file)
@@ -1,24 +1,60 @@
 
-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:
-    def byte_stream(file):
-        return file.buffer
-else:
-    def byte_stream(file):
-        return file
-
+def byte_stream(file):
+    return file.buffer
 
 def path_msg(x):
-    """Return a string representation of a path.
-
-    For now, assume that the destination encoding is going to be
-    ISO-8859-1, which it should be, for the primary current
-    destination, stderr, given the current bup-python.
-
-    """
+    """Return a string representation of a path."""
     # FIXME: configurability (might git-config quotePath be involved?)
-    return x.decode(encoding='iso-8859-1')
+    return x.decode(errors='backslashreplace')
+
+
+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 __new__(cls, *args, **kwargs):
+        result = super().__new__(cls, *args, **kwargs)
+        result._bup_closed = True  # supports __del__
+        return result
+
+    def __init__(self, *args, **kwargs):
+        # 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().__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