Files
2026-07-13 13:22:34 +08:00

153 lines
5.1 KiB
Python

from __future__ import annotations
from typing import Any
import pytest
from packaging.specifiers import SpecifierSet
from packaging.version import Version
from pypi._models import Package
_DEFAULT_UPLOAD = "2024-01-01T00:00:00Z"
def _payload(releases: dict[str, list[dict[str, Any]]]) -> dict[str, Any]:
# Inject a default upload_time into every non-empty dist so tests don't
# have to spell it out — `from_json` skips releases that lack one.
normalized = {
v: [{"upload_time_iso_8601": _DEFAULT_UPLOAD, **d} for d in dists]
for v, dists in releases.items()
}
return {"info": {"name": "demo", "summary": "demo package"}, "releases": normalized}
def test_versions_are_parsed_to_packaging_version() -> None:
pkg = Package.from_json(
_payload({
"1.0.0": [{"upload_time_iso_8601": "2024-01-01T00:00:00Z"}],
"2.0.0": [{"upload_time_iso_8601": "2024-06-01T00:00:00Z"}],
})
)
assert all(isinstance(v, Version) for v in pkg.versions)
assert pkg.versions == (Version("1.0.0"), Version("2.0.0"))
def test_releases_without_distributions_are_dropped() -> None:
pkg = Package.from_json(
_payload({
"1.0.0": [{}],
"0.5.0": [], # all distributions deleted on PyPI
})
)
assert pkg.versions == (Version("1.0.0"),)
def test_releases_without_upload_time_are_dropped() -> None:
raw = {
"info": {"name": "demo"},
"releases": {
"1.0.0": [{"upload_time_iso_8601": "2024-01-01T00:00:00Z"}],
"0.5.0": [{"filename": "demo-0.5.0.tar.gz"}], # missing upload_time
},
}
pkg = Package.from_json(raw)
assert pkg.versions == (Version("1.0.0"),)
def test_invalid_versions_are_dropped() -> None:
pkg = Package.from_json(
_payload({
"1.0.0": [{"upload_time_iso_8601": "2024-01-01T00:00:00Z"}],
"2004d": [{"upload_time_iso_8601": "2024-01-01T00:00:00Z"}],
})
)
assert pkg.versions == (Version("1.0.0"),)
@pytest.mark.parametrize(
("releases", "expected"),
[
({"1.0.0": [{}], "2.0.0": [{}]}, Version("2.0.0")),
({"1.0.0": [{}], "2.0.0a1": [{}]}, Version("1.0.0")),
({"1.0.0": [{}], "2.0.0.dev1": [{}]}, Version("1.0.0")),
({"1.0.0": [{"yanked": True}], "0.9.0": [{}]}, Version("0.9.0")),
({}, None),
],
)
def test_latest_version_skips_pre_dev_and_yanked(
releases: dict[str, list[dict[str, Any]]], expected: Version | None
) -> None:
pkg = Package.from_json(_payload(releases))
assert pkg.latest_version == expected
def test_get_release_accepts_str_or_version() -> None:
pkg = Package.from_json(_payload({"1.2.3": [{}]}))
by_str = pkg.get_release("1.2.3")
by_version = pkg.get_release(Version("1.2.3"))
assert by_str is not None
assert by_str is by_version
assert pkg.get_release("9.9.9") is None
def test_release_upload_time_picks_earliest() -> None:
pkg = Package.from_json(
_payload({
"1.0.0": [
{"upload_time_iso_8601": "2024-03-01T00:00:00Z"},
{"upload_time_iso_8601": "2024-01-01T00:00:00Z"},
],
})
)
release = pkg.get_release("1.0.0")
assert release is not None
assert release.upload_time is not None
assert release.upload_time.year == 2024
assert release.upload_time.month == 1
def test_release_yanked_only_when_all_distributions_yanked() -> None:
pkg = Package.from_json(_payload({"1.0.0": [{"yanked": True}, {"yanked": False}]}))
release = pkg.get_release("1.0.0")
assert release is not None
assert release.yanked is False
def test_release_yanked_when_every_distribution_yanked() -> None:
pkg = Package.from_json(_payload({"1.0.0": [{"yanked": True}, {"yanked": True}]}))
release = pkg.get_release("1.0.0")
assert release is not None
assert release.yanked is True
def test_release_requires_python_parsed_to_specifier_set() -> None:
pkg = Package.from_json(_payload({"1.0.0": [{"requires_python": ">=3.10,<4"}]}))
release = pkg.get_release("1.0.0")
assert release is not None
assert release.requires_python == SpecifierSet(">=3.10,<4")
assert Version("3.11") in release.requires_python
assert Version("3.9") not in release.requires_python
def test_release_requires_python_picks_first_non_empty() -> None:
pkg = Package.from_json(
_payload({
"1.0.0": [
{"requires_python": ""},
{"requires_python": ">=3.10"},
{"requires_python": ">=3.11"},
]
})
)
release = pkg.get_release("1.0.0")
assert release is not None
assert release.requires_python == SpecifierSet(">=3.10")
@pytest.mark.parametrize("raw", [None, "", "not a specifier"])
def test_release_requires_python_none_for_missing_or_invalid(raw: str | None) -> None:
payload_dist = {} if raw is None else {"requires_python": raw}
pkg = Package.from_json(_payload({"1.0.0": [payload_dist]}))
release = pkg.get_release("1.0.0")
assert release is not None
assert release.requires_python is None