Skip to content

Commit

Permalink
Drop support for Python 3.8
Browse files Browse the repository at this point in the history
  • Loading branch information
Secrus committed Oct 12, 2024
1 parent 05c87b2 commit 814b775
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 49 deletions.
4 changes: 2 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def lint(session):
session.run("pre-commit", "run", "--all-files", *args)


@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3"])
@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "pypy3"])
def test(session):
session.install(".")
session.install("-r", "tests/requirements.txt")
Expand All @@ -43,7 +43,7 @@ def test(session):
)


@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3"])
@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "pypy3"])
def doctest(session):
session.install(".")
session.install("-r", "docs/requirements.txt")
Expand Down
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ readme = "README.md"
authors = [
{ name = "Pradyun Gedam", email = "[email protected]" },
]
requires-python = ">=3.8"
requires-python = ">=3.9"
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dynamic = [
"description",
Expand All @@ -28,6 +28,7 @@ dynamic = [
"GitHub" = "https://github.com/pypa/installer"

[tool.ruff]
target-version = "py39"
fix = true
extend-exclude = [
"noxfile.py",
Expand All @@ -42,6 +43,7 @@ select = [
"I",
"ISC",
"D",
"UP"
]
ignore = [
"D105",
Expand Down
5 changes: 3 additions & 2 deletions src/installer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import os.path
import sys
import sysconfig
from typing import Dict, Optional, Sequence
from collections.abc import Sequence
from typing import Optional

import installer
from installer.destinations import SchemeDictionaryDestination
Expand Down Expand Up @@ -61,7 +62,7 @@ def _get_main_parser() -> argparse.ArgumentParser:

def _get_scheme_dict(
distribution_name: str, prefix: Optional[str] = None
) -> Dict[str, str]:
) -> dict[str, str]:
"""Calculate the scheme dictionary for the current Python environment."""
vars = {}
if prefix is None:
Expand Down
6 changes: 3 additions & 3 deletions src/installer/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import posixpath
from io import BytesIO
from typing import Dict, Tuple, cast
from typing import cast

from installer.destinations import WheelDestination
from installer.exceptions import InvalidWheelSource
Expand Down Expand Up @@ -35,7 +35,7 @@ def _process_WHEEL_file(source: WheelSource) -> Scheme:

def _determine_scheme(
path: str, source: WheelSource, root_scheme: Scheme
) -> Tuple[Scheme, str]:
) -> tuple[Scheme, str]:
"""Determine which scheme to place given path in, from source."""
data_dir = source.data_dir

Expand Down Expand Up @@ -64,7 +64,7 @@ def _determine_scheme(
def install(
source: WheelSource,
destination: WheelDestination,
additional_metadata: Dict[str, bytes],
additional_metadata: dict[str, bytes],
) -> None:
"""Install wheel described by ``source`` into ``destination``.
Expand Down
11 changes: 4 additions & 7 deletions src/installer/destinations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

import io
import os
from collections.abc import Collection, Iterable
from dataclasses import dataclass
from pathlib import Path
from typing import (
TYPE_CHECKING,
BinaryIO,
Collection,
Dict,
Iterable,
Optional,
Tuple,
Union,
)

Expand Down Expand Up @@ -83,7 +80,7 @@ def finalize_installation(
self,
scheme: Scheme,
record_file_path: str,
records: Iterable[Tuple[Scheme, RecordEntry]],
records: Iterable[tuple[Scheme, RecordEntry]],
) -> None:
"""Finalize installation, after all the files are written.
Expand All @@ -105,7 +102,7 @@ def finalize_installation(
class SchemeDictionaryDestination(WheelDestination):
"""Destination, based on a mapping of {scheme: file-system-path}."""

scheme_dict: Dict[str, str]
scheme_dict: dict[str, str]
"""A mapping of {scheme: file-system-path}"""

interpreter: str
Expand Down Expand Up @@ -260,7 +257,7 @@ def finalize_installation(
self,
scheme: Scheme,
record_file_path: str,
records: Iterable[Tuple[Scheme, RecordEntry]],
records: Iterable[tuple[Scheme, RecordEntry]],
) -> None:
"""Finalize installation, by writing the ``RECORD`` file & compiling bytecode.
Expand Down
9 changes: 5 additions & 4 deletions src/installer/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import csv
import hashlib
import os
from collections.abc import Iterable, Iterator
from dataclasses import dataclass
from typing import BinaryIO, Iterable, Iterator, Optional, Tuple, cast
from typing import BinaryIO, Optional, cast

from installer.utils import copyfileobj_with_hashing, get_stream_length

Expand Down Expand Up @@ -91,7 +92,7 @@ class RecordEntry:
size: Optional[int]
"""File's size in bytes."""

def to_row(self, path_prefix: Optional[str] = None) -> Tuple[str, str, str]:
def to_row(self, path_prefix: Optional[str] = None) -> tuple[str, str, str]:
"""Convert this into a 3-element tuple that can be written in a RECORD file.
:param path_prefix: A prefix to attach to the path -- must end in `/`
Expand Down Expand Up @@ -216,7 +217,7 @@ def from_elements(cls, path: str, hash_: str, size: str) -> "RecordEntry":
return cls(path=path, hash_=hash_value, size=size_value)


def parse_record_file(rows: Iterable[str]) -> Iterator[Tuple[str, str, str]]:
def parse_record_file(rows: Iterable[str]) -> Iterator[tuple[str, str, str]]:
"""Parse a :pep:`376` RECORD.
Returns an iterable of 3-value tuples, that can be passed to
Expand All @@ -233,5 +234,5 @@ def parse_record_file(rows: Iterable[str]) -> Iterator[Tuple[str, str, str]]:
# Convert Windows paths to use / for consistency
elements[0] = elements[0].replace("\\", "/")

value = cast(Tuple[str, str, str], tuple(elements))
value = cast(tuple[str, str, str], tuple(elements))
yield value
21 changes: 6 additions & 15 deletions src/installer/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@
import io
import os
import shlex
import sys
import zipfile
from collections.abc import Mapping
from dataclasses import dataclass, field
from types import ModuleType
from typing import TYPE_CHECKING, Mapping, Optional, Tuple, Union

if sys.version_info >= (3, 9): # pragma: no cover
from importlib.resources import files

def read_binary(package: Union[str, ModuleType], file_path: str) -> bytes:
return (files(package) / file_path).read_bytes()

else: # pragma: no cover
from importlib.resources import read_binary
from importlib.resources import files
from typing import TYPE_CHECKING, Optional

from installer import _scripts

Expand All @@ -30,7 +21,7 @@ def read_binary(package: Union[str, ModuleType], file_path: str) -> bytes:
__all__ = ["InvalidScript", "Script"]


_ALLOWED_LAUNCHERS: Mapping[Tuple["ScriptSection", "LauncherKind"], str] = {
_ALLOWED_LAUNCHERS: Mapping[tuple["ScriptSection", "LauncherKind"], str] = {
("console", "win-ia32"): "t32.exe",
("console", "win-amd64"): "t64.exe",
("console", "win-arm"): "t_arm.exe",
Expand Down Expand Up @@ -119,7 +110,7 @@ def _get_launcher_data(self, kind: "LauncherKind") -> Optional[bytes]:
except KeyError:
error = f"{key!r} not in {sorted(_ALLOWED_LAUNCHERS)!r}"
raise InvalidScript(error) from None
return read_binary(_scripts, name)
return (files(_scripts) / name).read_bytes()

def _get_alternate_executable(self, executable: str, kind: "LauncherKind") -> str:
"""Get an alternate executable for the launcher.
Expand All @@ -132,7 +123,7 @@ def _get_alternate_executable(self, executable: str, kind: "LauncherKind") -> st
executable = os.path.join(dn, fn)
return executable

def generate(self, executable: str, kind: "LauncherKind") -> Tuple[str, bytes]:
def generate(self, executable: str, kind: "LauncherKind") -> tuple[str, bytes]:
"""Generate a launcher for this script.
:param executable: Path to the executable to invoke.
Expand Down
15 changes: 8 additions & 7 deletions src/installer/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
import posixpath
import stat
import zipfile
from collections.abc import Iterator
from contextlib import contextmanager
from typing import BinaryIO, ClassVar, Iterator, List, Optional, Tuple, Type, cast
from typing import BinaryIO, ClassVar, Optional, cast

from installer.exceptions import InstallerError
from installer.records import RecordEntry, parse_record_file
from installer.utils import canonicalize_name, parse_wheel_filename

WheelContentElement = Tuple[Tuple[str, str, str], BinaryIO, bool]
WheelContentElement = tuple[tuple[str, str, str], BinaryIO, bool]


__all__ = ["WheelSource", "WheelFile"]
Expand All @@ -23,7 +24,7 @@ class WheelSource:
This is an abstract class, whose methods have to be implemented by subclasses.
"""

validation_error: ClassVar[Type[Exception]] = ValueError #: :meta hide-value:
validation_error: ClassVar[type[Exception]] = ValueError #: :meta hide-value:
"""
.. versionadded:: 0.7.0
Expand Down Expand Up @@ -52,7 +53,7 @@ def data_dir(self) -> str:
return f"{self.distribution}-{self.version}.data"

@property
def dist_info_filenames(self) -> List[str]:
def dist_info_filenames(self) -> list[str]:
"""Get names of all files in the dist-info directory.
Sample usage/behaviour::
Expand Down Expand Up @@ -113,7 +114,7 @@ def get_contents(self) -> Iterator[WheelContentElement]:
class _WheelFileValidationError(ValueError, InstallerError):
"""Raised when a wheel file fails validation."""

def __init__(self, issues: List[str]) -> None:
def __init__(self, issues: list[str]) -> None:
super().__init__(repr(issues))
self.issues = issues

Expand Down Expand Up @@ -208,7 +209,7 @@ def dist_info_dir(self) -> str:
return dist_info_dir

@property
def dist_info_filenames(self) -> List[str]:
def dist_info_filenames(self) -> list[str]:
"""Get names of all files in the dist-info directory."""
base = self.dist_info_dir
return [
Expand Down Expand Up @@ -246,7 +247,7 @@ def validate_record(self, *, validate_contents: bool = True) -> None:
[f"Unable to retrieve `RECORD` from {self._zipfile.filename}: {exc!r}"]
) from exc

issues: List[str] = []
issues: list[str] = []

for item in self._zipfile.infolist():
if item.filename[-1:] == "/": # looks like a directory
Expand Down
12 changes: 5 additions & 7 deletions src/installer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import re
import sys
from collections import namedtuple
from collections.abc import Iterable, Iterator
from configparser import ConfigParser
from email.message import Message
from email.parser import FeedParser
Expand All @@ -17,11 +18,8 @@
TYPE_CHECKING,
BinaryIO,
Callable,
Iterable,
Iterator,
NewType,
Optional,
Tuple,
Union,
cast,
)
Expand All @@ -31,7 +29,7 @@
from installer.scripts import LauncherKind, ScriptSection

Scheme = NewType("Scheme", str)
AllSchemes = Tuple[Scheme, ...]
AllSchemes = tuple[Scheme, ...]

__all__ = [
"parse_metadata_file",
Expand Down Expand Up @@ -117,7 +115,7 @@ def copyfileobj_with_hashing(
source: BinaryIO,
dest: BinaryIO,
hash_algorithm: str,
) -> Tuple[str, int]:
) -> tuple[str, int]:
"""Copy a buffer while computing the content's hash and size.
Copies the source buffer into the destination buffer while computing the
Expand Down Expand Up @@ -206,7 +204,7 @@ def fix_shebang(stream: BinaryIO, interpreter: str) -> Iterator[BinaryIO]:


def construct_record_file(
records: Iterable[Tuple[Scheme, "RecordEntry"]],
records: Iterable[tuple[Scheme, "RecordEntry"]],
prefix_for_scheme: Callable[[Scheme], Optional[str]] = lambda _: None,
) -> BinaryIO:
"""Construct a RECORD file.
Expand All @@ -228,7 +226,7 @@ def construct_record_file(
return stream.detach()


def parse_entrypoints(text: str) -> Iterable[Tuple[str, str, str, "ScriptSection"]]:
def parse_entrypoints(text: str) -> Iterable[tuple[str, str, str, "ScriptSection"]]:
"""Parse ``entry_points.txt``-style files.
:param text: entire contents of the file
Expand Down

0 comments on commit 814b775

Please sign in to comment.