--- a/mercurial/utils/compression.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/utils/compression.py Sun Oct 06 09:45:02 2019 -0400
@@ -15,9 +15,7 @@
i18n,
pycompat,
)
-from . import (
- stringutil,
-)
+from . import stringutil
safehasattr = pycompat.safehasattr
@@ -29,14 +27,17 @@
SERVERROLE = 'server'
CLIENTROLE = 'client'
-compewireprotosupport = collections.namedtuple(r'compenginewireprotosupport',
- (r'name', r'serverpriority',
- r'clientpriority'))
+compewireprotosupport = collections.namedtuple(
+ r'compenginewireprotosupport',
+ (r'name', r'serverpriority', r'clientpriority'),
+)
+
class propertycache(object):
def __init__(self, func):
self.func = func
self.name = func.__name__
+
def __get__(self, obj, type=None):
result = self.func(obj)
self.cachevalue(obj, result)
@@ -46,6 +47,7 @@
# __dict__ assignment required to bypass __setattr__ (eg: repoview)
obj.__dict__[self.name] = value
+
class compressormanager(object):
"""Holds registrations of various compression engines.
@@ -56,6 +58,7 @@
Compressors are registered against the global instance by calling its
``register()`` method.
"""
+
def __init__(self):
self._engines = {}
# Bundle spec human name to engine name.
@@ -87,19 +90,23 @@
name = engine.name()
if name in self._engines:
- raise error.Abort(_('compression engine %s already registered') %
- name)
+ raise error.Abort(
+ _('compression engine %s already registered') % name
+ )
bundleinfo = engine.bundletype()
if bundleinfo:
bundlename, bundletype = bundleinfo
if bundlename in self._bundlenames:
- raise error.Abort(_('bundle name %s already registered') %
- bundlename)
+ raise error.Abort(
+ _('bundle name %s already registered') % bundlename
+ )
if bundletype in self._bundletypes:
- raise error.Abort(_('bundle type %s already registered by %s') %
- (bundletype, self._bundletypes[bundletype]))
+ raise error.Abort(
+ _('bundle type %s already registered by %s')
+ % (bundletype, self._bundletypes[bundletype])
+ )
# No external facing name declared.
if bundlename:
@@ -111,16 +118,22 @@
if wiresupport:
wiretype = wiresupport.name
if wiretype in self._wiretypes:
- raise error.Abort(_('wire protocol compression %s already '
- 'registered by %s') %
- (wiretype, self._wiretypes[wiretype]))
+ raise error.Abort(
+ _(
+ 'wire protocol compression %s already '
+ 'registered by %s'
+ )
+ % (wiretype, self._wiretypes[wiretype])
+ )
self._wiretypes[wiretype] = name
revlogheader = engine.revlogheader()
if revlogheader and revlogheader in self._revlogheaders:
- raise error.Abort(_('revlog header %s already registered by %s') %
- (revlogheader, self._revlogheaders[revlogheader]))
+ raise error.Abort(
+ _('revlog header %s already registered by %s')
+ % (revlogheader, self._revlogheaders[revlogheader])
+ )
if revlogheader:
self._revlogheaders[revlogheader] = name
@@ -144,8 +157,9 @@
"""
engine = self._engines[self._bundlenames[bundlename]]
if not engine.available():
- raise error.Abort(_('compression engine %s could not be loaded') %
- engine.name())
+ raise error.Abort(
+ _('compression engine %s could not be loaded') % engine.name()
+ )
return engine
def forbundletype(self, bundletype):
@@ -157,8 +171,9 @@
"""
engine = self._engines[self._bundletypes[bundletype]]
if not engine.available():
- raise error.Abort(_('compression engine %s could not be loaded') %
- engine.name())
+ raise error.Abort(
+ _('compression engine %s could not be loaded') % engine.name()
+ )
return engine
def supportedwireengines(self, role, onlyavailable=True):
@@ -189,8 +204,9 @@
def forwiretype(self, wiretype):
engine = self._engines[self._wiretypes[wiretype]]
if not engine.available():
- raise error.Abort(_('compression engine %s could not be loaded') %
- engine.name())
+ raise error.Abort(
+ _('compression engine %s could not be loaded') % engine.name()
+ )
return engine
def forrevlogheader(self, header):
@@ -200,13 +216,16 @@
"""
return self._engines[self._revlogheaders[header]]
+
compengines = compressormanager()
+
class compressionengine(object):
"""Base class for compression engines.
Compression engines must implement the interface defined by this class.
"""
+
def name(self):
"""Returns the name of the compression engine.
@@ -319,6 +338,7 @@
"""
raise NotImplementedError()
+
class _CompressedStreamReader(object):
def __init__(self, fh):
if safehasattr(fh, 'unbufferedread'):
@@ -338,13 +358,13 @@
while self._pending:
if len(self._pending[0]) > l + self._pos:
newbuf = self._pending[0]
- buf.append(newbuf[self._pos:self._pos + l])
+ buf.append(newbuf[self._pos : self._pos + l])
self._pos += l
return ''.join(buf)
newbuf = self._pending.pop(0)
if self._pos:
- buf.append(newbuf[self._pos:])
+ buf.append(newbuf[self._pos :])
l -= len(newbuf) - self._pos
else:
buf.append(newbuf)
@@ -359,10 +379,12 @@
# No progress and no new data, bail out
return ''.join(buf)
+
class _GzipCompressedStreamReader(_CompressedStreamReader):
def __init__(self, fh):
super(_GzipCompressedStreamReader, self).__init__(fh)
self._decompobj = zlib.decompressobj()
+
def _decompress(self, chunk):
newbuf = self._decompobj.decompress(chunk)
if newbuf:
@@ -376,10 +398,12 @@
except zlib.error:
pass
+
class _BZ2CompressedStreamReader(_CompressedStreamReader):
def __init__(self, fh):
super(_BZ2CompressedStreamReader, self).__init__(fh)
self._decompobj = bz2.BZ2Decompressor()
+
def _decompress(self, chunk):
newbuf = self._decompobj.decompress(chunk)
if newbuf:
@@ -394,6 +418,7 @@
except EOFError:
self._eof = True
+
class _TruncatedBZ2CompressedStreamReader(_BZ2CompressedStreamReader):
def __init__(self, fh):
super(_TruncatedBZ2CompressedStreamReader, self).__init__(fh)
@@ -401,11 +426,13 @@
if newbuf:
self._pending.append(newbuf)
+
class _ZstdCompressedStreamReader(_CompressedStreamReader):
def __init__(self, fh, zstd):
super(_ZstdCompressedStreamReader, self).__init__(fh)
self._zstd = zstd
self._decompobj = zstd.ZstdDecompressor().decompressobj()
+
def _decompress(self, chunk):
newbuf = self._decompobj.decompress(chunk)
if newbuf:
@@ -420,6 +447,7 @@
except self._zstd.ZstdError:
self._eof = True
+
class _zlibengine(compressionengine):
def name(self):
return 'zlib'
@@ -456,7 +484,6 @@
return _GzipCompressedStreamReader(fh)
class zlibrevlogcompressor(object):
-
def __init__(self, level=None):
self._level = level
@@ -488,7 +515,7 @@
parts = []
pos = 0
while pos < insize:
- pos2 = pos + 2**20
+ pos2 = pos + 2 ** 20
parts.append(z.compress(data[pos:pos2]))
pos = pos2
parts.append(z.flush())
@@ -501,8 +528,10 @@
try:
return zlib.decompress(data)
except zlib.error as e:
- raise error.StorageError(_('revlog decompress error: %s') %
- stringutil.forcebytestr(e))
+ raise error.StorageError(
+ _('revlog decompress error: %s')
+ % stringutil.forcebytestr(e)
+ )
def revlogcompressor(self, opts=None):
level = None
@@ -510,8 +539,10 @@
level = opts.get('zlib.level')
return self.zlibrevlogcompressor(level)
+
compengines.register(_zlibengine())
+
class _bz2engine(compressionengine):
def name(self):
return 'bz2'
@@ -548,8 +579,10 @@
def decompressorreader(self, fh):
return _BZ2CompressedStreamReader(fh)
+
compengines.register(_bz2engine())
+
class _truncatedbz2engine(compressionengine):
def name(self):
return 'bz2truncated'
@@ -562,8 +595,10 @@
def decompressorreader(self, fh):
return _TruncatedBZ2CompressedStreamReader(fh)
+
compengines.register(_truncatedbz2engine())
+
class _noopengine(compressionengine):
def name(self):
return 'none'
@@ -597,8 +632,10 @@
def revlogcompressor(self, opts=None):
return self.nooprevlogcompressor()
+
compengines.register(_noopengine())
+
class _zstdengine(compressionengine):
def name(self):
return 'zstd'
@@ -609,6 +646,7 @@
# until first access.
try:
from .. import zstd
+
# Force delayed import.
zstd.__version__
return zstd
@@ -716,8 +754,10 @@
return ''.join(chunks)
except Exception as e:
- raise error.StorageError(_('revlog decompress error: %s') %
- stringutil.forcebytestr(e))
+ raise error.StorageError(
+ _('revlog decompress error: %s')
+ % stringutil.forcebytestr(e)
+ )
def revlogcompressor(self, opts=None):
opts = opts or {}
@@ -728,8 +768,10 @@
level = 3
return self.zstdrevlogcompressor(self._module, level=level)
+
compengines.register(_zstdengine())
+
def bundlecompressiontopics():
"""Obtains a list of available bundle compressions for use in help."""
# help.makeitemsdocs() expects a dict of names to items with a .__doc__.
@@ -761,4 +803,5 @@
return items
+
i18nfunctions = bundlecompressiontopics().values()