Pass Requirement objects around (#12709)

This allows us to keep metadata like python_version and platform_system
and use it to conditionally install packages.
This commit is contained in:
Sebastian Rittau
2024-09-30 17:45:58 +02:00
committed by GitHub
parent 06b50fcc27
commit 3b385903a1
6 changed files with 47 additions and 41 deletions

View File

@@ -131,7 +131,7 @@ class StubMetadata:
"""
version: str
requires: Annotated[list[str], "The raw requirements as listed in METADATA.toml"]
requires: Annotated[list[Requirement], "The parsed requirements as listed in METADATA.toml"]
extra_description: str | None
stub_distribution: Annotated[str, "The name under which the distribution is uploaded to PyPI"]
upstream_repository: Annotated[str, "The URL of the upstream repository"] | None
@@ -201,14 +201,9 @@ def read_metadata(distribution: str) -> StubMetadata:
# Check that the version parses
Version(version[:-2] if version.endswith(".*") else version)
requires: object = data.get("requires", [])
assert isinstance(requires, list)
for req in requires:
assert isinstance(req, str), f"Invalid requirement {req!r} for {distribution!r}"
for space in " \t\n":
assert space not in req, f"For consistency, requirement should not have whitespace: {req!r}"
# Check that the requirement parses
Requirement(req)
requires_s: object = data.get("requires", [])
assert isinstance(requires_s, list)
requires = [parse_requires(distribution, req) for req in requires_s]
extra_description: object = data.get("extra_description")
assert isinstance(extra_description, (str, type(None)))
@@ -292,9 +287,16 @@ def read_metadata(distribution: str) -> StubMetadata:
)
def parse_requires(distribution: str, req: object) -> Requirement:
assert isinstance(req, str), f"Invalid requirement {req!r} for {distribution!r}"
for space in " \t\n":
assert space not in req, f"For consistency, requirement should not have whitespace: {req!r}"
return Requirement(req)
class PackageDependencies(NamedTuple):
typeshed_pkgs: tuple[str, ...]
external_pkgs: tuple[str, ...]
typeshed_pkgs: tuple[Requirement, ...]
external_pkgs: tuple[Requirement, ...]
@cache
@@ -317,17 +319,15 @@ def read_dependencies(distribution: str) -> PackageDependencies:
If a typeshed stub is removed, this function will consider it to be an external dependency.
"""
pypi_name_to_typeshed_name_mapping = get_pypi_name_to_typeshed_name_mapping()
typeshed: list[str] = []
external: list[str] = []
typeshed: list[Requirement] = []
external: list[Requirement] = []
for dependency in read_metadata(distribution).requires:
maybe_typeshed_dependency = Requirement(dependency).name
if maybe_typeshed_dependency in pypi_name_to_typeshed_name_mapping:
typeshed.append(pypi_name_to_typeshed_name_mapping[maybe_typeshed_dependency])
if dependency.name in pypi_name_to_typeshed_name_mapping:
req = Requirement(str(dependency)) # copy the requirement
req.name = pypi_name_to_typeshed_name_mapping[dependency.name]
typeshed.append(req)
else:
# convert to Requirement and then back to str
# to make sure that the requirements all have a normalised string representation
# (This will also catch any malformed requirements early)
external.append(str(Requirement(dependency)))
external.append(dependency)
return PackageDependencies(tuple(typeshed), tuple(external))
@@ -341,13 +341,13 @@ def get_recursive_requirements(package_name: str) -> PackageDependencies:
`get_recursive_requirements("caldav")` will determine that the stubs for `caldav`
have both `requests` and `urllib3` as typeshed-internal dependencies.
"""
typeshed: set[str] = set()
external: set[str] = set()
typeshed: set[Requirement] = set()
external: set[Requirement] = set()
non_recursive_requirements = read_dependencies(package_name)
typeshed.update(non_recursive_requirements.typeshed_pkgs)
external.update(non_recursive_requirements.external_pkgs)
for pkg in non_recursive_requirements.typeshed_pkgs:
reqs = get_recursive_requirements(pkg)
reqs = get_recursive_requirements(pkg.name)
typeshed.update(reqs.typeshed_pkgs)
external.update(reqs.external_pkgs)
return PackageDependencies(tuple(sorted(typeshed)), tuple(sorted(external)))
return PackageDependencies(tuple(typeshed), tuple(external))