Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-py7zr for openSUSE:Factory checked in at 2024-01-04 15:58:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-py7zr (Old) and /work/SRC/openSUSE:Factory/.python-py7zr.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-py7zr" Thu Jan 4 15:58:18 2024 rev:8 rq:1136541 version:0.20.8 Changes: -------- --- /work/SRC/openSUSE:Factory/python-py7zr/python-py7zr.changes 2023-12-15 21:49:55.583982149 +0100 +++ /work/SRC/openSUSE:Factory/.python-py7zr.new.28375/python-py7zr.changes 2024-01-04 16:00:32.419407474 +0100 @@ -1,0 +2,8 @@ +Wed Dec 27 13:59:12 UTC 2023 - Dirk Müller <[email protected]> + +- update to 0.20.8: + * Detect brotli import error (#543) + * refactor: hardening SevenZipFile constructor (#547) + * refactor: improve type safe functions (#545) + +------------------------------------------------------------------- Old: ---- py7zr-0.20.7.tar.gz New: ---- py7zr-0.20.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-py7zr.spec ++++++ --- /var/tmp/diff_new_pack.6BRsRC/_old 2024-01-04 16:00:32.923425886 +0100 +++ /var/tmp/diff_new_pack.6BRsRC/_new 2024-01-04 16:00:32.927426033 +0100 @@ -26,7 +26,7 @@ %endif %{?sle15_python_module_pythons} Name: python-py7zr%{psuffix} -Version: 0.20.7 +Version: 0.20.8 Release: 0 Summary: Library and utility to support 7zip License: LGPL-2.1-or-later ++++++ py7zr-0.20.7.tar.gz -> py7zr-0.20.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/.git_archival.txt new/py7zr-0.20.8/.git_archival.txt --- old/py7zr-0.20.7/.git_archival.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/py7zr-0.20.8/.git_archival.txt 2023-11-14 00:22:36.000000000 +0100 @@ -0,0 +1,4 @@ +node: $Format:%H$ +node-date: $Format:%cI$ +describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ +ref-names: $Format:%D$ \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/.gitattributes new/py7zr-0.20.8/.gitattributes --- old/py7zr-0.20.7/.gitattributes 1970-01-01 01:00:00.000000000 +0100 +++ new/py7zr-0.20.8/.gitattributes 2023-11-14 00:22:36.000000000 +0100 @@ -0,0 +1 @@ +.git_archival.txt export-subst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/MANIFEST.in new/py7zr-0.20.8/MANIFEST.in --- old/py7zr-0.20.7/MANIFEST.in 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/MANIFEST.in 2023-11-14 00:22:36.000000000 +0100 @@ -1,6 +1,7 @@ include *.rst include *.svg include *.toml +include *.txt include .flake8 include LICENSE include py7zr/py.typed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/PKG-INFO new/py7zr-0.20.8/PKG-INFO --- old/py7zr-0.20.7/PKG-INFO 2023-11-05 23:40:07.002969000 +0100 +++ new/py7zr-0.20.8/PKG-INFO 2023-11-14 00:22:49.225569700 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: py7zr -Version: 0.20.7 +Version: 0.20.8 Summary: Pure python 7-zip library Author-email: Hiroshi Miura <[email protected]> License: LGPL-2.1-or-later @@ -62,6 +62,7 @@ Provides-Extra: check Requires-Dist: mypy>=0.940; extra == "check" Requires-Dist: mypy_extensions>=0.4.1; extra == "check" +Requires-Dist: lxml; extra == "check" Requires-Dist: types-psutil; extra == "check" Requires-Dist: check-manifest; extra == "check" Requires-Dist: flake8<7; extra == "check" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/docs/Changelog.rst new/py7zr-0.20.8/docs/Changelog.rst --- old/py7zr-0.20.7/docs/Changelog.rst 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/docs/Changelog.rst 2023-11-14 00:22:36.000000000 +0100 @@ -9,6 +9,18 @@ `Unreleased`_ ============= +`v0.20.8`_ +========== +Fixed +----- +* Detect brotli import error (#543) + +Changed +------- +* refactor: hardening SevenZipFile constructor (#547) +* refactor: improve type safe functions (#545) +* chore: add git export configuration (#544) + `v0.20.7`_ ========== Changed @@ -351,7 +363,8 @@ .. History links -.. _Unreleased: https://github.com/miurahr/py7zr/compare/v0.20.7...HEAD +.. _Unreleased: https://github.com/miurahr/py7zr/compare/v0.20.8...HEAD +.. _v0.20.8: https://github.com/miurahr/py7zr/compare/v0.20.7...v0.20.8 .. _v0.20.7: https://github.com/miurahr/py7zr/compare/v0.20.6...v0.20.7 .. _v0.20.6: https://github.com/miurahr/py7zr/compare/v0.20.5...v0.20.6 .. _v0.20.5: https://github.com/miurahr/py7zr/compare/v0.20.4...v0.20.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/docs/user_guide.rst new/py7zr-0.20.8/docs/user_guide.rst --- old/py7zr-0.20.7/docs/user_guide.rst 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/docs/user_guide.rst 2023-11-14 00:22:36.000000000 +0100 @@ -24,8 +24,9 @@ $ pip install py7zr The py7zr depends on several external libraries. You should install these libraries with py7zr. -There are ``PyCryptodome``, ``PyZstd``, ``PyPPMd``, ``bcj-cffi``, ``texttable``, and ``multivolumefile``. -These pakcages are automatically installed when installing with ``pip`` command. +There are `PyCryptodomex`_, `PyZstd`_, `PyPPMd`_, `pybcj`_, `texttable`_, and `multivolumefile`_. +There are also dependency whether `Brotli`_ or `BrotliCFFI`_ depends on your python flavour. +These packages are automatically installed when installing with ``pip`` command. Dependencies ------------ @@ -56,6 +57,21 @@ .. _`multivolumefile` : https://pypi.org/project/multivolumefile .. _`texttable` : https://pypi.org/project/texttable +.. note:: + + There is known issue when you run ``py7zr`` on Windows platform. + `issue#527`_ report that when installed on Azure VM Windows, + it failed to import `Brotli`_ library even when ``pip install`` + was successfully executed. It is because `Brotli`_ library depends + ``vc_redist.x64`` Microsoft system library which should be come with + python distribution, but Brotli library does not find the DLL in search + path on certain environment. Please check details at `Brotli Issue#782`_ + + Current ``py7zr`` detect the import failure, and raise exception only when + user try to compress/decompress with Brotli compression algorithm. + +.. _`issue#527`: https://github.com/miurahr/py7zr/issues/527 +.. _`Brotli Issue#782`: https://github.com/google/brotli/issues/782#issuecomment-559516099 Run Command diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr/archiveinfo.py new/py7zr-0.20.8/py7zr/archiveinfo.py --- old/py7zr-0.20.7/py7zr/archiveinfo.py 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/py7zr/archiveinfo.py 2023-11-14 00:22:36.000000000 +0100 @@ -31,7 +31,7 @@ from io import BytesIO from operator import and_, or_ from struct import pack, unpack -from typing import Any, BinaryIO, Dict, List, Optional, Tuple +from typing import Any, BinaryIO, Dict, List, Optional, Tuple, Union from py7zr.compressor import SevenZipCompressor, SevenZipDecompressor from py7zr.exceptions import Bad7zFile @@ -43,12 +43,27 @@ P7ZIP_MINOR_VERSION = b"\x04" +class WriteWithCrc(io.RawIOBase): + """Thin wrapper for file object to calculate crc32 when write called.""" + + def __init__(self, fp: BinaryIO): + self._fp = fp + self.digest = 0 + + def write(self, data): + self.digest = calculate_crc32(data, self.digest) + return self._fp.write(data) + + def tell(self): + return self._fp.tell() + + def read_crcs(file: BinaryIO, count: int) -> List[int]: data = file.read(4 * count) return [unpack("<L", data[i * 4 : i * 4 + 4])[0] for i in range(count)] -def write_crcs(file: BinaryIO, crcs): +def write_crcs(file: Union[BinaryIO, WriteWithCrc], crcs): for crc in crcs: write_uint32(file, crc) @@ -57,11 +72,11 @@ return ord(file.read(1)) -def write_bytes(file: BinaryIO, data: bytes): +def write_bytes(file: Union[BinaryIO, WriteWithCrc], data: bytes): return file.write(data) -def write_byte(file: BinaryIO, data): +def write_byte(file: Union[BinaryIO, WriteWithCrc], data): assert len(data) == 1 return write_bytes(file, data) @@ -80,7 +95,7 @@ return a, res -def write_uint32(file: BinaryIO, value): +def write_uint32(file: Union[BinaryIO, WriteWithCrc], value): """write uint32 value in 4 bytes.""" b = pack("<L", value) file.write(b) @@ -116,12 +131,12 @@ return value + (highpart << (vlen * 8)) -def write_real_uint64(file: BinaryIO, value: int): +def write_real_uint64(file: Union[BinaryIO, WriteWithCrc], value: int): """write 8 bytes, as an unsigned long long.""" file.write(pack("<Q", value)) -def write_uint64(file: BinaryIO, value: int): +def write_uint64(file: Union[BinaryIO, WriteWithCrc], value: int): """ UINT64 means real UINT64 encoded with the following scheme: @@ -176,7 +191,7 @@ return result -def write_boolean(file: BinaryIO, booleans: List[bool], all_defined: bool = False): +def write_boolean(file: Union[BinaryIO, WriteWithCrc], booleans: List[bool], all_defined: bool = False): if all_defined and reduce(and_, booleans, True): file.write(b"\x01") return @@ -200,7 +215,7 @@ return val.decode("utf-16LE") -def write_utf16(file: BinaryIO, val: str): +def write_utf16(file: Union[BinaryIO, WriteWithCrc], val: str): """write a utf-16 string to file""" for c in val: file.write(c.encode("utf-16LE")) @@ -256,7 +271,7 @@ self.enable_digests = len(self.crcs) > 0 return self - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): assert self.packpos is not None assert self.numstreams == len(self.packsizes) write_byte(file, PROPERTY.PACK_INFO) @@ -506,7 +521,7 @@ "end id expected but 0x{:02x} found at 0x{:08x}".format(ord(pid), file.tell()) ) # pragma: no-cover # noqa - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): assert self.numfolders == len(self.folders) file.write(PROPERTY.UNPACK_INFO) file.write(PROPERTY.FOLDER) @@ -596,7 +611,7 @@ self.digestsdefined = [False] * num_digests_total self.digests = [0] * num_digests_total - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): if len(self.num_unpackstreams_folders) == 0: # pragma: no-cover # nothing to write return write_byte(file, PROPERTY.SUBSTREAMS_INFO) @@ -654,7 +669,7 @@ if pid != PROPERTY.END: raise Bad7zFile("end id expected but %s found" % repr(pid)) # pragma: no-cover - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): write_byte(file, PROPERTY.MAIN_STREAMS_INFO) if self.packinfo is not None: self.packinfo.write(file) @@ -676,7 +691,7 @@ self.unpackinfo: UnpackInfo = UnpackInfo() self.unpackinfo.numfolders = 1 - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): write_byte(file, PROPERTY.ENCODED_HEADER) self.packinfo.write(file) self.unpackinfo.write(file) @@ -776,7 +791,7 @@ for i, f in enumerate(self.files): f["startpos"] = read_real_uint64(fp)[0] if defined[i] else None - def _write_times(self, fp: BinaryIO, propid, name: str) -> None: + def _write_times(self, fp: Union[BinaryIO, WriteWithCrc], propid, name: str) -> None: write_byte(fp, propid) defined = [] # type: List[bool] num_defined = 0 # type: int @@ -799,7 +814,7 @@ else: pass - def _write_prop_bool_vector(self, fp: BinaryIO, propid, vector) -> None: + def _write_prop_bool_vector(self, fp: Union[BinaryIO, WriteWithCrc], propid, vector) -> None: write_byte(fp, propid) write_boolean(fp, vector, all_defined=False) @@ -810,7 +825,7 @@ return True return False - def _write_names(self, file: BinaryIO): + def _write_names(self, file: Union[BinaryIO, WriteWithCrc]): name_defined = 0 names = [] name_size = 0 @@ -846,7 +861,7 @@ if defined[i]: write_uint32(file, f["attributes"]) - def write(self, file: BinaryIO): + def write(self, file: Union[BinaryIO, WriteWithCrc]): assert self.files is not None write_byte(file, PROPERTY.FILES_INFO) numfiles = len(self.files) @@ -882,21 +897,6 @@ write_byte(file, PROPERTY.END) -class WriteWithCrc: - """Thin wrapper for file object to calculate crc32 when write called.""" - - def __init__(self, fp: BinaryIO): - self._fp = fp - self.digest = 0 - - def write(self, data): - self.digest = calculate_crc32(data, self.digest) - return self._fp.write(data) - - def tell(self): - return self._fp.tell() - - class Header: """the archive header""" @@ -904,12 +904,13 @@ def __init__(self) -> None: self.solid: bool = False - self.main_streams = None - self.files_info = None + self.main_streams: Optional[StreamsInfo] = None + self.files_info: Optional[FilesInfo] = None self.size: int = 0 self._start_pos: int = 0 self.password: Optional[str] = None self._initialized: bool = False + self.filters: Optional[List[Dict[str, int]]] = None @classmethod def retrieve(cls, fp: BinaryIO, buffer: BytesIO, start_pos: int, password=None): @@ -992,7 +993,7 @@ # actual header start position startpos = file.tell() crcfile = WriteWithCrc(file) - headerstreams.write(crcfile) # type: ignore # noqa + headerstreams.write(crcfile) digest = crcfile.digest return startpos, digest @@ -1006,12 +1007,12 @@ startpos, headercrc = self._encode_header(file, afterheader, filters) else: crcfile = WriteWithCrc(file) - write_byte(crcfile, PROPERTY.HEADER) # type: ignore # noqa + write_byte(crcfile, PROPERTY.HEADER) if self.main_streams is not None: self.main_streams.write(crcfile) if self.files_info is not None: self.files_info.write(crcfile) - write_byte(crcfile, PROPERTY.END) # type: ignore + write_byte(crcfile, PROPERTY.END) headercrc = crcfile.digest endpos = file.tell() header_len = endpos - startpos @@ -1043,9 +1044,15 @@ folder.prepare_coderinfo(self.filters) if self.main_streams is not None: # append mode - self.main_streams.unpackinfo.folders.append(folder) - self.main_streams.unpackinfo.numfolders += 1 - self.main_streams.substreamsinfo.num_unpackstreams_folders.append(0) + if self.main_streams.unpackinfo is not None: + self.main_streams.unpackinfo.folders.append(folder) + self.main_streams.unpackinfo.numfolders += 1 + else: + pass # unexpected + if self.main_streams.substreamsinfo is not None: + self.main_streams.substreamsinfo.num_unpackstreams_folders.append(0) + else: + pass # unexpected else: # create new header folders = [folder] @@ -1069,7 +1076,9 @@ self.main_streams.packinfo.crcs = [] return folder else: - return self.main_streams.unpackinfo.folders[-1] + if self.main_streams is not None and self.main_streams.unpackinfo is not None: + return self.main_streams.unpackinfo.folders[-1] + return None # unexpected class SignatureHeader: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr/cli.py new/py7zr-0.20.8/py7zr/cli.py --- old/py7zr-0.20.7/py7zr/cli.py 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/py7zr/cli.py 2023-11-14 00:22:36.000000000 +0100 @@ -150,7 +150,8 @@ @staticmethod def _get_version(): s = inspect.stack() - module_name = inspect.getmodule(s[0][0]).__name__ + _module = inspect.getmodule(s[0][0]) + module_name = _module.__name__ if _module is not None else "unknown" py_version = platform.python_version() py_impl = platform.python_implementation() py_build = platform.python_compiler() @@ -177,7 +178,7 @@ table.set_cols_align(["l", "r"]) for f in SupportedMethods.formats: m = "".join(" {:02x}".format(x) for x in f["magic"]) - table.add_row([f["name"], m]) + table.add_row([str(f["name"]), m]) print(table.draw()) print("\nCodecs and hashes:") table = texttable.Texttable() @@ -185,8 +186,10 @@ table.set_cols_dtype(["t", "t"]) table.set_cols_align(["l", "r"]) for c in SupportedMethods.methods: - m = "".join("{:02x}".format(x) for x in c["id"]) - table.add_row([m, c["name"]]) + method_id: bytes = c["id"] + m = "".join("{:02x}".format(x) for x in method_id) + method_name: str = c["name"] + table.add_row([m, method_name]) table.add_row(["0", "CRC32"]) if is_check_supported(CHECK_SHA256): table.add_row(["0", "SHA256"]) @@ -218,10 +221,11 @@ archive_info = a.archiveinfo() archive_list = a.list() if verbose: - if isinstance(target, io.IOBase): - file.write("Listing archive: {}\n".format(target.name)) + if isinstance(target, io.FileIO) or isinstance(target, multivolumefile.MultiVolume): + file_name: str = target.name # type: ignore else: - file.write("Listing archive: {}\n".format(str(target))) + file_name = str(target) + file.write("Listing archive: {}\n".format(file_name)) file.write("--\n") file.write("Path = {}\n".format(archive_info.filename)) file.write("Type = 7z\n") @@ -385,9 +389,12 @@ def _volumesize_unitconv(self, size: str) -> int: m = self.unit_pattern.match(size) - num = m.group(1) - unit = m.group(2) - return int(num) if unit is None else int(num) * self.dunits[unit] + if m is not None: + num = m.group(1) + unit = m.group(2) + return int(num) if unit is None else int(num) * self.dunits[unit] + else: + return -1 def run_create(self, args): sztarget = args.arcfile # type: str diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr/compressor.py new/py7zr-0.20.8/py7zr/compressor.py --- old/py7zr-0.20.7/py7zr/compressor.py 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/py7zr/compressor.py 2023-11-14 00:22:36.000000000 +0100 @@ -66,7 +66,10 @@ try: import brotli # type: ignore # noqa except ImportError: - import brotlicffi as brotli # type: ignore # noqa + try: + import brotlicffi as brotli # type: ignore # noqa + except ImportError: + brotli = None brotli_major = 1 brotli_minor = 0 @@ -475,6 +478,11 @@ class BrotliCompressor(ISevenZipCompressor): def __init__(self, level): + if brotli is None: + raise UnsupportedCompressionMethodError( + None, + "Brotli library load error may be happened. Please check your environment have a required system library.", + ) self._compressor = brotli.Compressor(quality=level) def compress(self, data: Union[bytes, bytearray, memoryview]) -> bytes: @@ -486,6 +494,11 @@ class BrotliDecompressor(ISevenZipDecompressor): def __init__(self, properties: bytes, block_size: int): + if brotli is None: + raise UnsupportedCompressionMethodError( + None, + "Brotli library load error may be happened. Please check your environment have a required system library.", + ) if len(properties) != 3: raise UnsupportedCompressionMethodError(properties, "Unknown size of properties are passed") if (properties[0], properties[1]) > (brotli_major, brotli_minor): @@ -549,6 +562,17 @@ } +class LZMA1Compressor(ISevenZipCompressor): + def __init__(self, filters): + self._compressor = lzma.LZMACompressor(format=lzma.FORMAT_RAW, filters=filters) + + def compress(self, data: Union[bytes, bytearray, memoryview]) -> bytes: + return self._compressor.compress(data) + + def flush(self) -> bytes: + return self._compressor.flush() + + class LZMA1Decompressor(ISevenZipDecompressor): def __init__(self, filters, unpacksize): self._decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_RAW, filters=filters) @@ -831,7 +855,7 @@ raise UnsupportedCompressionMethodError(filters, "Unknown combination of methods.") def _set_native_compressors_coders(self, filters): - self.chain.append(lzma.LZMACompressor(format=lzma.FORMAT_RAW, filters=filters)) + self.chain.append(LZMA1Compressor(filters)) self._unpacksizes.append(0) for filter in filters: self.coders.insert(0, SupportedMethods.get_coder(filter)) @@ -897,14 +921,16 @@ data += compressor.flush() else: data = compressor.flush() + if data is None: + return 0 self.packsize += len(data) self.digest = calculate_crc32(data, self.digest) fp.write(data) return len(data) @property - def unpacksizes(self): - result = [] + def unpacksizes(self) -> List[int]: + result: List[int] = [] shift = 0 prev = False for i, r in enumerate(self.methods_map): @@ -923,8 +949,8 @@ class SupportedMethods: """Hold list of methods.""" - formats = [{"name": "7z", "magic": MAGIC_7Z}] - methods = [ + formats: List[Dict[str, Any]] = [{"name": "7z", "magic": MAGIC_7Z}] + methods: List[Dict[str, Any]] = [ { "id": COMPRESSION_METHOD.COPY, "name": "COPY", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr/py7zr.py new/py7zr-0.20.8/py7zr/py7zr.py --- old/py7zr-0.20.7/py7zr/py7zr.py 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/py7zr/py7zr.py 2023-11-14 00:22:36.000000000 +0100 @@ -335,8 +335,12 @@ blocksize: Optional[int] = None, mp: bool = False, ) -> None: + # check invalid mode. if mode not in ("r", "w", "x", "a"): raise ValueError("ZipFile requires mode 'r', 'w', 'x', or 'a'") + # early check unsupported mode. + if mode == "x": + raise NotImplementedError self.fp: BinaryIO self.mp = mp self.password_protected = password is not None @@ -393,15 +397,13 @@ self._real_get_contents(password) self.fp.seek(self.afterheader) # seek into start of payload and prepare worker to extract self.worker = Worker(self.files, self.afterheader, self.header, self.mp) - elif mode in "w": + elif mode == "w": self._prepare_write(filters, password) - elif mode in "x": - raise NotImplementedError elif mode == "a": self._real_get_contents(password) self._prepare_append(filters, password) else: - raise ValueError("Mode must be 'r', 'w', 'x', or 'a'") + raise ValueError("Mode must be 'r', 'w', 'x', or 'a'") # never come here except Exception as e: self._fpclose() raise e @@ -468,21 +470,8 @@ if not file_info["emptystream"] and folders is not None: folder = folders[pstat.folder] numinstreams = max([coder.get("numinstreams", 1) for coder in folder.coders]) - ( - maxsize, - compressed, - uncompressed, - packsize, - solid, - ) = self._get_fileinfo_sizes( - pstat, - subinfo, - packinfo, - folder, - packsizes, - unpacksizes, - file_in_solid, - numinstreams, + (maxsize, compressed, uncompressed, packsize, solid) = self._get_fileinfo_sizes( + pstat, subinfo, packinfo, folder, packsizes, unpacksizes, file_in_solid, numinstreams ) pstat.input += 1 folder.solid = solid @@ -692,10 +681,11 @@ self.worker = Worker(self.files, self.afterheader, self.header, self.mp) def _write_flush(self): - if self.header._initialized: - folder = self.header.main_streams.unpackinfo.folders[-1] - self.worker.flush_archive(self.fp, folder) - self._write_header() + if self.header is not None: + if self.header._initialized: + folder = self.header.main_streams.unpackinfo.folders[-1] + self.worker.flush_archive(self.fp, folder) + self._write_header() def _write_header(self): """Write header and update signature header.""" @@ -806,7 +796,7 @@ return False def _var_release(self): - self._dict = None + self._dict = {} self.worker.close() del self.worker del self.files @@ -1458,12 +1448,12 @@ Find the target member of a symlink or hardlink member in the archive. """ targetname: str = target.as_posix() - linkname = readlink(targetname) + linkname: Union[str, pathlib.Path] = readlink(targetname) # Check windows full path symlinks - if linkname.startswith("\\\\?\\"): - linkname = linkname[4:] + if str(linkname).startswith("\\\\?\\"): + linkname = str(linkname)[4:] # normalize as posix style - linkname: str = pathlib.Path(linkname).as_posix() + linkname = pathlib.Path(linkname).as_posix() member = None for j in range(len(self.files)): if linkname == self.files[j].origin.as_posix(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr/version.py new/py7zr-0.20.8/py7zr/version.py --- old/py7zr-0.20.7/py7zr/version.py 2023-11-05 23:40:06.000000000 +0100 +++ new/py7zr-0.20.8/py7zr/version.py 2023-11-14 00:22:49.000000000 +0100 @@ -1 +1 @@ -__version__ = "0.20.7" +__version__ = "0.20.8" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr.egg-info/PKG-INFO new/py7zr-0.20.8/py7zr.egg-info/PKG-INFO --- old/py7zr-0.20.7/py7zr.egg-info/PKG-INFO 2023-11-05 23:40:06.000000000 +0100 +++ new/py7zr-0.20.8/py7zr.egg-info/PKG-INFO 2023-11-14 00:22:49.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: py7zr -Version: 0.20.7 +Version: 0.20.8 Summary: Pure python 7-zip library Author-email: Hiroshi Miura <[email protected]> License: LGPL-2.1-or-later @@ -62,6 +62,7 @@ Provides-Extra: check Requires-Dist: mypy>=0.940; extra == "check" Requires-Dist: mypy_extensions>=0.4.1; extra == "check" +Requires-Dist: lxml; extra == "check" Requires-Dist: types-psutil; extra == "check" Requires-Dist: check-manifest; extra == "check" Requires-Dist: flake8<7; extra == "check" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr.egg-info/SOURCES.txt new/py7zr-0.20.8/py7zr.egg-info/SOURCES.txt --- old/py7zr-0.20.7/py7zr.egg-info/SOURCES.txt 2023-11-05 23:40:06.000000000 +0100 +++ new/py7zr-0.20.8/py7zr.egg-info/SOURCES.txt 2023-11-14 00:22:49.000000000 +0100 @@ -1,4 +1,6 @@ .flake8 +.git_archival.txt +.gitattributes LICENSE MANIFEST.in README.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/py7zr.egg-info/requires.txt new/py7zr-0.20.8/py7zr.egg-info/requires.txt --- old/py7zr-0.20.7/py7zr.egg-info/requires.txt 2023-11-05 23:40:06.000000000 +0100 +++ new/py7zr-0.20.8/py7zr.egg-info/requires.txt 2023-11-14 00:22:49.000000000 +0100 @@ -21,6 +21,7 @@ [check] mypy>=0.940 mypy_extensions>=0.4.1 +lxml types-psutil check-manifest flake8<7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py7zr-0.20.7/pyproject.toml new/py7zr-0.20.8/pyproject.toml --- old/py7zr-0.20.7/pyproject.toml 2023-11-05 23:39:48.000000000 +0100 +++ new/py7zr-0.20.8/pyproject.toml 2023-11-14 00:22:36.000000000 +0100 @@ -76,6 +76,7 @@ check = [ "mypy>=0.940", "mypy_extensions>=0.4.1", + "lxml", "types-psutil", "check-manifest", "flake8<7", @@ -139,8 +140,10 @@ [tool.mypy] warn_redundant_casts = true warn_unused_ignores = true +warn_return_any = false strict_optional = true show_column_numbers = true +check_untyped_defs = true [tool.check-manifest] ignore = ["py7zr/version.py", "azure-pipelines.yml", ".readthedocs.yml", "codecov.yml"] @@ -205,7 +208,7 @@ [testenv:mypy] extras = check -commands = mypy py7zr +commands = mypy --html-report build/mypy py7zr deps = pyzstd
