Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General typing improvement #610

Merged
merged 4 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/wheel/_setuptools_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import sys


def _not_warning(record):
def _not_warning(record: logging.LogRecord) -> bool:

Check warning on line 8 in src/wheel/_setuptools_logging.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/_setuptools_logging.py#L8

Added line #L8 was not covered by tests
return record.levelno < logging.WARNING


def configure():
def configure() -> None:

Check warning on line 12 in src/wheel/_setuptools_logging.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/_setuptools_logging.py#L12

Added line #L12 was not covered by tests
"""
Configure logging to emit warning and above to stderr
and everything else to stdout. This behavior is provided
Expand Down
70 changes: 40 additions & 30 deletions src/wheel/bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from email.policy import EmailPolicy
from glob import iglob
from shutil import rmtree
from typing import TYPE_CHECKING, Callable, Iterable, Literal, Sequence, cast
from zipfile import ZIP_DEFLATED, ZIP_STORED

import setuptools
Expand All @@ -31,15 +32,18 @@
from .vendored.packaging import version as _packaging_version
from .wheelfile import WheelFile

if TYPE_CHECKING:
import types

Check warning on line 36 in src/wheel/bdist_wheel.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/bdist_wheel.py#L36

Added line #L36 was not covered by tests

def safe_name(name):

def safe_name(name: str) -> str:
"""Convert an arbitrary string to a standard distribution name
Any runs of non-alphanumeric/. characters are replaced with a single '-'.
"""
return re.sub("[^A-Za-z0-9.]+", "-", name)


def safe_version(version):
def safe_version(version: str) -> str:
"""
Convert an arbitrary string to a standard version string
"""
Expand All @@ -56,15 +60,15 @@
PY_LIMITED_API_PATTERN = r"cp3\d"


def _is_32bit_interpreter():
def _is_32bit_interpreter() -> bool:
return struct.calcsize("P") == 4


def python_tag():
def python_tag() -> str:
return f"py{sys.version_info[0]}"


def get_platform(archive_root):
def get_platform(archive_root: str | None) -> str:
"""Return our platform name 'win32', 'linux_x86_64'"""
result = sysconfig.get_platform()
if result.startswith("macosx") and archive_root is not None:
Expand All @@ -82,7 +86,9 @@
return result.replace("-", "_")


def get_flag(var, fallback, expected=True, warn=True):
def get_flag(
var: str, fallback: bool, expected: bool = True, warn: bool = True
) -> bool:
"""Use a fallback value for determining SOABI flags if the needed config
var is unset or unavailable."""
val = sysconfig.get_config_var(var)
Expand All @@ -97,9 +103,9 @@
return val == expected


def get_abi_tag():
def get_abi_tag() -> str | None:
"""Return the ABI tag based on SOABI (if available) or emulate SOABI (PyPy2)."""
soabi = sysconfig.get_config_var("SOABI")
soabi: str = sysconfig.get_config_var("SOABI")
impl = tags.interpreter_name()
if not soabi and impl in ("cp", "pp") and hasattr(sys, "maxunicode"):
d = ""
Expand Down Expand Up @@ -137,19 +143,23 @@
return abi


def safer_name(name):
def safer_name(name: str) -> str:
return safe_name(name).replace("-", "_")


def safer_version(version):
def safer_version(version: str) -> str:
return safe_version(version).replace("-", "_")


def remove_readonly(func, path, excinfo):
def remove_readonly(
func: Callable[..., object],
path: str,
excinfo: tuple[type[Exception], Exception, types.TracebackType],
) -> None:
remove_readonly_exc(func, path, excinfo[1])


def remove_readonly_exc(func, path, exc):
def remove_readonly_exc(func: Callable[..., object], path: str, exc: Exception) -> None:
os.chmod(path, stat.S_IWRITE)
func(path)

Expand Down Expand Up @@ -224,24 +234,24 @@
boolean_options = ["keep-temp", "skip-build", "relative", "universal"]

def initialize_options(self):
self.bdist_dir = None
self.bdist_dir: str = None
self.data_dir = None
self.plat_name = None
self.plat_name: str | None = None
self.plat_tag = None
self.format = "zip"
self.keep_temp = False
self.dist_dir = None
self.dist_dir: str | None = None
self.egginfo_dir = None
self.root_is_pure = None
self.root_is_pure: bool | None = None
self.skip_build = None
self.relative = False
self.owner = None
self.group = None
self.universal = False
self.compression = "deflated"
self.python_tag = python_tag()
self.build_number = None
self.py_limited_api = False
self.universal: bool = False
self.compression: str | int = "deflated"
self.python_tag: str = python_tag()
self.build_number: str | None = None
self.py_limited_api: str | Literal[False] = False
self.plat_name_supplied = False

def finalize_options(self):
Expand Down Expand Up @@ -298,11 +308,11 @@
components += (self.build_number,)
return "-".join(components)

def get_tag(self):
def get_tag(self) -> tuple[str, str, str]:
# bdist sets self.plat_name if unset, we should only use it for purepy
# wheels if the user supplied it.
if self.plat_name_supplied:
plat_name = self.plat_name
plat_name = cast(str, self.plat_name)
elif self.root_is_pure:
plat_name = "any"
else:
Expand Down Expand Up @@ -447,7 +457,7 @@
rmtree(self.bdist_dir, onexc=remove_readonly_exc)

def write_wheelfile(
self, wheelfile_base, generator="bdist_wheel (" + wheel_version + ")"
self, wheelfile_base: str, generator: str = f"bdist_wheel ({wheel_version})"
):
from email.message import Message

Expand All @@ -470,24 +480,24 @@
with open(wheelfile_path, "wb") as f:
BytesGenerator(f, maxheaderlen=0).flatten(msg)

def _ensure_relative(self, path):
def _ensure_relative(self, path: str) -> str:
# copied from dir_util, deleted
drive, path = os.path.splitdrive(path)
if path[0:1] == os.sep:
path = drive + path[1:]
return path

@property
def license_paths(self):
def license_paths(self) -> Iterable[str]:
if setuptools_major_version >= 57:
# Setuptools has resolved any patterns to actual file names
return self.distribution.metadata.license_files or ()

files = set()
files: set[str] = set()

Check warning on line 496 in src/wheel/bdist_wheel.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/bdist_wheel.py#L496

Added line #L496 was not covered by tests
metadata = self.distribution.get_option_dict("metadata")
if setuptools_major_version >= 42:
# Setuptools recognizes the license_files option but does not do globbing
patterns = self.distribution.metadata.license_files
patterns = cast(Sequence[str], self.distribution.metadata.license_files)

Check warning on line 500 in src/wheel/bdist_wheel.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/bdist_wheel.py#L500

Added line #L500 was not covered by tests
else:
# Prior to those, wheel is entirely responsible for handling license files
if "license_files" in metadata:
Expand Down Expand Up @@ -522,10 +532,10 @@

return files

def egg2dist(self, egginfo_path, distinfo_path):
def egg2dist(self, egginfo_path: str, distinfo_path: str):
"""Convert an .egg-info directory into a .dist-info directory"""

def adios(p):
def adios(p: str) -> None:
"""Appropriately delete directory, file or link."""
if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p):
shutil.rmtree(p)
Expand Down
10 changes: 5 additions & 5 deletions src/wheel/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ class WheelError(Exception):
pass


def unpack_f(args):
def unpack_f(args: argparse.Namespace) -> None:
from .unpack import unpack

unpack(args.wheelfile, args.dest)


def pack_f(args):
def pack_f(args: argparse.Namespace) -> None:
from .pack import pack

pack(args.directory, args.dest_dir, args.build_number)


def convert_f(args):
def convert_f(args: argparse.Namespace) -> None:
from .convert import convert

convert(args.files, args.dest_dir, args.verbose)


def tags_f(args):
def tags_f(args: argparse.Namespace) -> None:
from .tags import tags

names = (
Expand All @@ -51,7 +51,7 @@ def tags_f(args):
print(name)


def version_f(args):
def version_f(args: argparse.Namespace) -> None:
from .. import __version__

print("wheel %s" % __version__)
Expand Down
8 changes: 4 additions & 4 deletions src/wheel/cli/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
shutil.rmtree(dir)


def parse_wininst_info(wininfo_name, egginfo_name):
def parse_wininst_info(wininfo_name: str, egginfo_name: str | None):
"""Extract metadata from filenames.

Extracts the 4 metadataitems needed (name, version, pyversion, arch) from
Expand Down Expand Up @@ -167,7 +167,7 @@
return {"name": w_name, "ver": w_ver, "arch": w_arch, "pyver": w_pyver}


def wininst2wheel(path, dest_dir):
def wininst2wheel(path: str, dest_dir: str) -> None:
with zipfile.ZipFile(path) as bdw:
# Search for egg-info in the archive
egginfo_name = None
Expand All @@ -193,7 +193,7 @@

# rewrite paths to trick ZipFile into extracting an egg
# XXX grab wininst .ini - between .exe, padding, and first zip file.
members = []
members: list[str] = []

Check warning on line 196 in src/wheel/cli/convert.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/cli/convert.py#L196

Added line #L196 was not covered by tests
egginfo_name = ""
for zipinfo in bdw.infolist():
key, basename = zipinfo.filename.split("/", 1)
Expand Down Expand Up @@ -257,7 +257,7 @@
shutil.rmtree(dir)


def convert(files, dest_dir, verbose):
def convert(files: list[str], dest_dir: str, verbose: bool) -> None:
for pat in files:
for installer in iglob(pat):
if os.path.splitext(installer)[1] == ".egg":
Expand Down
31 changes: 22 additions & 9 deletions src/wheel/macosx_libfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
import ctypes
import os
import sys
from io import BufferedIOBase
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Union

Check warning on line 50 in src/wheel/macosx_libfile.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/macosx_libfile.py#L50

Added line #L50 was not covered by tests

StrPath = Union[str, os.PathLike[str]]

Check warning on line 52 in src/wheel/macosx_libfile.py

View check run for this annotation

Codecov / codecov/patch

src/wheel/macosx_libfile.py#L52

Added line #L52 was not covered by tests

"""here the needed const and struct from mach-o header files"""

Expand Down Expand Up @@ -238,7 +245,7 @@
"""


def swap32(x):
def swap32(x: int) -> int:
return (
((x << 24) & 0xFF000000)
| ((x << 8) & 0x00FF0000)
Expand All @@ -247,7 +254,10 @@
)


def get_base_class_and_magic_number(lib_file, seek=None):
def get_base_class_and_magic_number(
lib_file: BufferedIOBase,
seek: int | None = None,
) -> tuple[type[ctypes.Structure], int]:
if seek is None:
seek = lib_file.tell()
else:
Expand All @@ -271,11 +281,11 @@
return BaseClass, magic_number


def read_data(struct_class, lib_file):
def read_data(struct_class: type[ctypes.Structure], lib_file: BufferedIOBase):
return struct_class.from_buffer_copy(lib_file.read(ctypes.sizeof(struct_class)))


def extract_macosx_min_system_version(path_to_lib):
def extract_macosx_min_system_version(path_to_lib: str):
with open(path_to_lib, "rb") as lib_file:
BaseClass, magic_number = get_base_class_and_magic_number(lib_file, 0)
if magic_number not in [FAT_MAGIC, FAT_MAGIC_64, MH_MAGIC, MH_MAGIC_64]:
Expand All @@ -301,7 +311,7 @@
read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch)
]

versions_list = []
versions_list: list[tuple[int, int, int]] = []
for el in fat_arch_list:
try:
version = read_mach_header(lib_file, el.offset)
Expand Down Expand Up @@ -333,7 +343,10 @@
return None


def read_mach_header(lib_file, seek=None):
def read_mach_header(
lib_file: BufferedIOBase,
seek: int | None = None,
) -> tuple[int, int, int] | None:
"""
This function parses a Mach-O header and extracts
information about the minimal macOS version.
Expand Down Expand Up @@ -380,14 +393,14 @@
continue


def parse_version(version):
def parse_version(version: int) -> tuple[int, int, int]:
x = (version & 0xFFFF0000) >> 16
y = (version & 0x0000FF00) >> 8
z = version & 0x000000FF
return x, y, z


def calculate_macosx_platform_tag(archive_root, platform_tag):
def calculate_macosx_platform_tag(archive_root: StrPath, platform_tag: str) -> str:
"""
Calculate proper macosx platform tag basing on files which are included to wheel

Expand Down Expand Up @@ -420,7 +433,7 @@

assert len(base_version) == 2
start_version = base_version
versions_dict = {}
versions_dict: dict[str, tuple[int, int]] = {}
for dirpath, _dirnames, filenames in os.walk(archive_root):
for filename in filenames:
if filename.endswith(".dylib") or filename.endswith(".so"):
Expand Down