update
This commit is contained in:
@@ -7,11 +7,22 @@ import re
|
||||
import stat
|
||||
import time
|
||||
from io import StringIO, TextIOWrapper
|
||||
from typing import IO, TYPE_CHECKING, Literal
|
||||
from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
|
||||
|
||||
from wheel.cli import WheelError
|
||||
from wheel.util import log, urlsafe_b64decode, urlsafe_b64encode
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Protocol, Sized, Union
|
||||
|
||||
from typing_extensions import Buffer
|
||||
|
||||
StrPath = Union[str, os.PathLike[str]]
|
||||
|
||||
class SizedBuffer(Sized, Buffer, Protocol): ...
|
||||
|
||||
|
||||
# Non-greedy matching of an optional build number may be too clever (more
|
||||
# invalid wheel filenames will match). Separate regex for .dist-info?
|
||||
WHEEL_INFO_RE = re.compile(
|
||||
@@ -22,7 +33,7 @@ WHEEL_INFO_RE = re.compile(
|
||||
MINIMUM_TIMESTAMP = 315532800 # 1980-01-01 00:00:00 UTC
|
||||
|
||||
|
||||
def get_zipinfo_datetime(timestamp=None):
|
||||
def get_zipinfo_datetime(timestamp: float | None = None):
|
||||
# Some applications need reproducible .whl files, but they can't do this without
|
||||
# forcing the timestamp of the individual ZipInfo objects. See issue #143.
|
||||
timestamp = int(os.environ.get("SOURCE_DATE_EPOCH", timestamp or time.time()))
|
||||
@@ -37,7 +48,12 @@ class WheelFile(ZipFile):
|
||||
|
||||
_default_algorithm = hashlib.sha256
|
||||
|
||||
def __init__(self, file, mode="r", compression=ZIP_DEFLATED):
|
||||
def __init__(
|
||||
self,
|
||||
file: StrPath,
|
||||
mode: Literal["r", "w", "x", "a"] = "r",
|
||||
compression: int = ZIP_DEFLATED,
|
||||
):
|
||||
basename = os.path.basename(file)
|
||||
self.parsed_filename = WHEEL_INFO_RE.match(basename)
|
||||
if not basename.endswith(".whl") or self.parsed_filename is None:
|
||||
@@ -49,7 +65,7 @@ class WheelFile(ZipFile):
|
||||
self.parsed_filename.group("namever")
|
||||
)
|
||||
self.record_path = self.dist_info_path + "/RECORD"
|
||||
self._file_hashes = {}
|
||||
self._file_hashes: dict[str, tuple[None, None] | tuple[int, bytes]] = {}
|
||||
self._file_sizes = {}
|
||||
if mode == "r":
|
||||
# Ignore RECORD and any embedded wheel signatures
|
||||
@@ -81,8 +97,8 @@ class WheelFile(ZipFile):
|
||||
|
||||
if algorithm.lower() in {"md5", "sha1"}:
|
||||
raise WheelError(
|
||||
"Weak hash algorithm ({}) is not permitted by PEP "
|
||||
"427".format(algorithm)
|
||||
f"Weak hash algorithm ({algorithm}) is not permitted by "
|
||||
f"PEP 427"
|
||||
)
|
||||
|
||||
self._file_hashes[path] = (
|
||||
@@ -90,8 +106,13 @@ class WheelFile(ZipFile):
|
||||
urlsafe_b64decode(hash_sum.encode("ascii")),
|
||||
)
|
||||
|
||||
def open(self, name_or_info, mode="r", pwd=None):
|
||||
def _update_crc(newdata):
|
||||
def open(
|
||||
self,
|
||||
name_or_info: str | ZipInfo,
|
||||
mode: Literal["r", "w"] = "r",
|
||||
pwd: bytes | None = None,
|
||||
) -> IO[bytes]:
|
||||
def _update_crc(newdata: bytes) -> None:
|
||||
eof = ef._eof
|
||||
update_crc_orig(newdata)
|
||||
running_hash.update(newdata)
|
||||
@@ -119,9 +140,9 @@ class WheelFile(ZipFile):
|
||||
|
||||
return ef
|
||||
|
||||
def write_files(self, base_dir):
|
||||
def write_files(self, base_dir: str):
|
||||
log.info(f"creating '{self.filename}' and adding '{base_dir}' to it")
|
||||
deferred = []
|
||||
deferred: list[tuple[str, str]] = []
|
||||
for root, dirnames, filenames in os.walk(base_dir):
|
||||
# Sort the directory names so that `os.walk` will walk them in a
|
||||
# defined order on the next iteration.
|
||||
@@ -141,7 +162,12 @@ class WheelFile(ZipFile):
|
||||
for path, arcname in deferred:
|
||||
self.write(path, arcname)
|
||||
|
||||
def write(self, filename, arcname=None, compress_type=None):
|
||||
def write(
|
||||
self,
|
||||
filename: str,
|
||||
arcname: str | None = None,
|
||||
compress_type: int | None = None,
|
||||
) -> None:
|
||||
with open(filename, "rb") as f:
|
||||
st = os.fstat(f.fileno())
|
||||
data = f.read()
|
||||
@@ -153,7 +179,12 @@ class WheelFile(ZipFile):
|
||||
zinfo.compress_type = compress_type or self.compression
|
||||
self.writestr(zinfo, data, compress_type)
|
||||
|
||||
def writestr(self, zinfo_or_arcname, data, compress_type=None):
|
||||
def writestr(
|
||||
self,
|
||||
zinfo_or_arcname: str | ZipInfo,
|
||||
data: SizedBuffer | str,
|
||||
compress_type: int | None = None,
|
||||
):
|
||||
if isinstance(zinfo_or_arcname, str):
|
||||
zinfo_or_arcname = ZipInfo(
|
||||
zinfo_or_arcname, date_time=get_zipinfo_datetime()
|
||||
|
||||
Reference in New Issue
Block a user