Update rarfile to 3.0 (3e54b22).

This commit is contained in:
JackDandy 2017-01-27 14:35:38 +00:00
parent acd59d3012
commit 4fb5b2ef46
2 changed files with 45 additions and 25 deletions

View file

@ -18,6 +18,7 @@
* Update moment.js 2.15.1 to 2.17.1 * Update moment.js 2.15.1 to 2.17.1
* Update PNotify library 2.1.0 to 3.0.0 (175af26) * Update PNotify library 2.1.0 to 3.0.0 (175af26)
* Update profilehooks 1.8.2.dev0 (ee3f1a8) to 1.9.0 (de7d59b) * Update profilehooks 1.8.2.dev0 (ee3f1a8) to 1.9.0 (de7d59b)
* Update rarfile to 3.0 (3e54b22)
[develop changelog] [develop changelog]

View file

@ -140,8 +140,12 @@ except ImportError:
_have_crypto = 0 _have_crypto = 0
try: try:
from pyblake2 import blake2s try:
_have_blake2 = True from hashlib import blake2s
_have_blake2 = True
except ImportError:
from pyblake2 import blake2s
_have_blake2 = True
except ImportError: except ImportError:
_have_blake2 = False _have_blake2 = False
@ -380,8 +384,8 @@ UTC = timezone(timedelta(0), 'UTC')
BSIZE = 32 * 1024 BSIZE = 32 * 1024
def _get_rar_version(xfile): def _get_rar_version(xfile):
'''Check quickly whether file is rar archive. """Check quickly whether file is rar archive.
''' """
with XFile(xfile) as fd: with XFile(xfile) as fd:
buf = fd.read(len(RAR5_ID)) buf = fd.read(len(RAR5_ID))
if buf.startswith(RAR_ID): if buf.startswith(RAR_ID):
@ -395,8 +399,8 @@ def _get_rar_version(xfile):
## ##
def is_rarfile(xfile): def is_rarfile(xfile):
'''Check quickly whether file is rar archive. """Check quickly whether file is rar archive.
''' """
return _get_rar_version(xfile) > 0 return _get_rar_version(xfile) > 0
class Error(Exception): class Error(Exception):
@ -473,7 +477,7 @@ class RarCannotExec(RarExecError):
class RarInfo(object): class RarInfo(object):
r'''An entry in rar archive. r"""An entry in rar archive.
RAR3 extended timestamps are :class:`datetime.datetime` objects without timezone. RAR3 extended timestamps are :class:`datetime.datetime` objects without timezone.
RAR5 extended timestamps are :class:`datetime.datetime` objects with UTC timezone. RAR5 extended timestamps are :class:`datetime.datetime` objects with UTC timezone.
@ -566,7 +570,7 @@ class RarInfo(object):
volume_file volume_file
Volume file name, where file starts. Volume file name, where file starts.
''' """
# zipfile-compatible fields # zipfile-compatible fields
filename = None filename = None
@ -616,8 +620,8 @@ class RarInfo(object):
class RarFile(object): class RarFile(object):
'''Parse RAR structure, provide access to files in archive. """Parse RAR structure, provide access to files in archive.
''' """
#: Archive comment. Unicode string or None. #: Archive comment. Unicode string or None.
comment = None comment = None
@ -662,13 +666,16 @@ class RarFile(object):
self._parse() self._parse()
def __enter__(self): def __enter__(self):
"""Open context."""
return self return self
def __exit__(self, typ, value, traceback): def __exit__(self, typ, value, traceback):
"""Exit context"""
self.close() self.close()
def setpassword(self, password): def setpassword(self, password):
'''Sets the password to use when extracting.''' """Sets the password to use when extracting.
"""
self._password = password self._password = password
if self._file_parser: if self._file_parser:
if self._file_parser.has_header_encryption(): if self._file_parser.has_header_encryption():
@ -679,33 +686,35 @@ class RarFile(object):
self._file_parser.setpassword(self._password) self._file_parser.setpassword(self._password)
def needs_password(self): def needs_password(self):
'''Returns True if any archive entries require password for extraction.''' """Returns True if any archive entries require password for extraction.
"""
return self._file_parser.needs_password() return self._file_parser.needs_password()
def namelist(self): def namelist(self):
'''Return list of filenames in archive.''' """Return list of filenames in archive.
"""
return [f.filename for f in self.infolist()] return [f.filename for f in self.infolist()]
def infolist(self): def infolist(self):
'''Return RarInfo objects for all files/directories in archive.''' """Return RarInfo objects for all files/directories in archive.
"""
return self._file_parser.infolist() return self._file_parser.infolist()
def volumelist(self): def volumelist(self):
'''Returns filenames of archive volumes. """Returns filenames of archive volumes.
In case of single-volume archive, the list contains In case of single-volume archive, the list contains
just the name of main archive file. just the name of main archive file.
''' """
return self._file_parser.volumelist() return self._file_parser.volumelist()
def getinfo(self, fname): def getinfo(self, fname):
'''Return RarInfo for file. """Return RarInfo for file.
''' """
return self._file_parser.getinfo(fname) return self._file_parser.getinfo(fname)
def open(self, fname, mode='r', psw=None): def open(self, fname, mode='r', psw=None):
'''Returns file-like object (:class:`RarExtFile`), """Returns file-like object (:class:`RarExtFile`) from where the data can be read.
from where the data can be read.
The object implements :class:`io.RawIOBase` interface, so it can The object implements :class:`io.RawIOBase` interface, so it can
be further wrapped with :class:`io.BufferedReader` be further wrapped with :class:`io.BufferedReader`
@ -726,7 +735,7 @@ class RarFile(object):
must be 'r' must be 'r'
psw psw
password to use for extracting. password to use for extracting.
''' """
if mode != 'r': if mode != 'r':
raise NotImplementedError("RarFile.open() supports only mode=r") raise NotImplementedError("RarFile.open() supports only mode=r")
@ -823,8 +832,7 @@ class RarFile(object):
check_returncode(p, output) check_returncode(p, output)
def strerror(self): def strerror(self):
"""Return error string if parsing failed, """Return error string if parsing failed or None if no problems.
or None if no problems.
""" """
if not self._file_parser: if not self._file_parser:
return "Not a RAR file" return "Not a RAR file"
@ -935,9 +943,14 @@ class CommonParser(object):
""" """
return self._info_list return self._info_list
def getinfo(self, fname): def getinfo(self, member):
"""Return RarInfo for filename """Return RarInfo for filename
""" """
if isinstance(member, RarInfo):
fname = member.filename
else:
fname = member
# accept both ways here # accept both ways here
if PATH_SEP == '/': if PATH_SEP == '/':
fname2 = fname.replace("\\", "/") fname2 = fname.replace("\\", "/")
@ -1951,6 +1964,8 @@ class RarExtFile(RawIOBase):
name = None name = None
def __init__(self, parser, inf): def __init__(self, parser, inf):
"""Open archive entry.
"""
super(RarExtFile, self).__init__() super(RarExtFile, self).__init__()
# standard io.* properties # standard io.* properties
@ -2100,7 +2115,8 @@ class RarExtFile(RawIOBase):
def writable(self): def writable(self):
"""Returns False. """Returns False.
Writing is not supported.""" Writing is not supported.
"""
return False return False
def seekable(self): def seekable(self):
@ -2856,6 +2872,7 @@ def hmac_sha256(key, data):
return HMAC(key, data, sha256).digest() return HMAC(key, data, sha256).digest()
def membuf_tempfile(memfile): def membuf_tempfile(memfile):
"""Write in-memory file object to real file."""
memfile.seek(0, 0) memfile.seek(0, 0)
tmpfd, tmpname = mkstemp(suffix='.rar') tmpfd, tmpname = mkstemp(suffix='.rar')
@ -2875,6 +2892,8 @@ def membuf_tempfile(memfile):
return tmpname return tmpname
class XTempFile(object): class XTempFile(object):
"""Real file for archive.
"""
__slots__ = ('_tmpfile', '_filename') __slots__ = ('_tmpfile', '_filename')
def __init__(self, rarfile): def __init__(self, rarfile):