From 21423960ebdbced7539e7b64274750a3c09cabd1 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 17 Nov 2025 18:06:46 -0500 Subject: [PATCH 1/3] chore: add -> to tests Signed-off-by: Henry Schreiner --- .pre-commit-config.yaml | 4 +- pyproject.toml | 3 +- tests/test_elffile.py | 12 +-- tests/test_licenses.py | 4 +- tests/test_manylinux.py | 32 +++--- tests/test_markers.py | 60 +++++------ tests/test_metadata.py | 140 +++++++++++++------------- tests/test_musllinux.py | 4 +- tests/test_specifiers.py | 70 ++++++------- tests/test_structures.py | 20 ++-- tests/test_tags.py | 210 ++++++++++++++++++++------------------- tests/test_utils.py | 18 ++-- tests/test_version.py | 52 +++++----- 13 files changed, 322 insertions(+), 307 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f99ad5cb..babe98878 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,9 +26,9 @@ repos: rev: v1.18.1 hooks: - id: mypy - exclude: '^(docs|tasks|tests)|setup\.py' + exclude: '^(docs|tasks)' args: [] - additional_dependencies: [pyparsing, nox, orjson] + additional_dependencies: [pyparsing, nox, orjson, 'pytest<9', tomli, tomli_w] - repo: https://github.com/codespell-project/codespell rev: "v2.4.1" diff --git a/pyproject.toml b/pyproject.toml index ceafb77e6..387dc2408 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,9 +80,10 @@ strict = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] warn_unused_ignores = true python_version = "3.8" +files = ["src", "tests", "noxfile.py"] [[tool.mypy.overrides]] -module = ["_manylinux"] +module = ["_manylinux", "pretend"] ignore_missing_imports = true [tool.ruff] diff --git a/tests/test_elffile.py b/tests/test_elffile.py index 809f033ac..fd2ba25ec 100644 --- a/tests/test_elffile.py +++ b/tests/test_elffile.py @@ -22,7 +22,7 @@ ("s390x-s390x", EIClass.C64, EIData.Msb, EMachine.S390), ], ) -def test_elffile_glibc(name, capacity, encoding, machine): +def test_elffile_glibc(name, capacity, encoding, machine) -> None: path = DIR_MANYLINUX.joinpath(f"hello-world-{name}") with path.open("rb") as f: ef = ELFFile(f) @@ -46,7 +46,7 @@ def test_elffile_glibc(name, capacity, encoding, machine): ("x86_64", EIClass.C64, EIData.Lsb, EMachine.X8664, "x86_64"), ], ) -def test_elffile_musl(name, capacity, encoding, machine, interpreter): +def test_elffile_musl(name, capacity, encoding, machine, interpreter) -> None: path = DIR_MUSLLINUX.joinpath(f"musl-{name}") with path.open("rb") as f: ef = ELFFile(f) @@ -68,25 +68,25 @@ def test_elffile_musl(name, capacity, encoding, machine, interpreter): ], ids=["no-magic", "wrong-magic", "unknown-format"], ) -def test_elffile_bad_ident(data): +def test_elffile_bad_ident(data) -> None: with pytest.raises(ELFInvalid): ELFFile(io.BytesIO(data)) -def test_elffile_no_section(): +def test_elffile_no_section() -> None: """Enough for magic, but not the section definitions.""" data = BIN_MUSL_X86_64[:25] with pytest.raises(ELFInvalid): ELFFile(io.BytesIO(data)) -def test_elffile_invalid_section(): +def test_elffile_invalid_section() -> None: """Enough for section definitions, but not the actual sections.""" data = BIN_MUSL_X86_64[:58] assert ELFFile(io.BytesIO(data)).interpreter is None -def test_elffle_no_interpreter_section(): +def test_elffle_no_interpreter_section() -> None: ef = ELFFile(io.BytesIO(BIN_MUSL_X86_64)) # Change all sections to *not* PT_INTERP. diff --git a/tests/test_licenses.py b/tests/test_licenses.py index 204f06688..39279f966 100644 --- a/tests/test_licenses.py +++ b/tests/test_licenses.py @@ -1,11 +1,11 @@ from packaging.licenses._spdx import EXCEPTIONS, LICENSES -def test_licenses(): +def test_licenses() -> None: for license_id in LICENSES: assert license_id == license_id.lower() -def test_exceptions(): +def test_exceptions() -> None: for exception_id in EXCEPTIONS: assert exception_id == exception_id.lower() diff --git a/tests/test_manylinux.py b/tests/test_manylinux.py index 637dddbd1..83b40e033 100644 --- a/tests/test_manylinux.py +++ b/tests/test_manylinux.py @@ -43,7 +43,9 @@ def manylinux_module(monkeypatch): @pytest.mark.parametrize( ("attribute", "glibc"), [("1", (2, 5)), ("2010", (2, 12)), ("2014", (2, 17))] ) -def test_module_declaration(monkeypatch, manylinux_module, attribute, glibc, tf): +def test_module_declaration( + monkeypatch, manylinux_module, attribute, glibc, tf +) -> None: manylinux = f"manylinux{attribute}_compatible" monkeypatch.setattr(manylinux_module, manylinux, tf, raising=False) res = _is_compatible("x86_64", glibc) @@ -64,14 +66,16 @@ def test_module_declaration_missing_attribute( @pytest.mark.parametrize( ("version", "compatible"), [((2, 0), True), ((2, 5), True), ((2, 10), False)] ) -def test_is_manylinux_compatible_glibc_support(version, compatible, monkeypatch): +def test_is_manylinux_compatible_glibc_support( + version, compatible, monkeypatch +) -> None: monkeypatch.setitem(sys.modules, "_manylinux", None) monkeypatch.setattr(_manylinux, "_get_glibc_version", lambda: (2, 5)) assert bool(_is_compatible("any", version)) == compatible @pytest.mark.parametrize("version_str", ["glibc-2.4.5", "2"]) -def test_check_glibc_version_warning(version_str): +def test_check_glibc_version_warning(version_str) -> None: msg = f"Expected glibc version with 2 components major.minor, got: {version_str}" with pytest.warns(RuntimeWarning, match=re.escape(msg)): _parse_glibc_version(version_str) @@ -86,7 +90,7 @@ def test_check_glibc_version_warning(version_str): ("2.4", "2.4"), ], ) -def test_glibc_version_string(version_str, expected, monkeypatch): +def test_glibc_version_string(version_str, expected, monkeypatch) -> None: class LibcVersion: def __init__(self, version_str): self.version_str = version_str @@ -108,12 +112,12 @@ def __init__(self, libc_version): assert _glibc_version_string() is None -def test_glibc_version_string_confstr(monkeypatch): +def test_glibc_version_string_confstr(monkeypatch) -> None: monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) assert _glibc_version_string_confstr() == "2.20" -def test_glibc_version_string_fail(monkeypatch): +def test_glibc_version_string_fail(monkeypatch) -> None: monkeypatch.setattr(os, "confstr", lambda _: None, raising=False) monkeypatch.setitem(sys.modules, "ctypes", None) assert _glibc_version_string() is None @@ -124,23 +128,23 @@ def test_glibc_version_string_fail(monkeypatch): "failure", [pretend.raiser(ValueError), pretend.raiser(OSError), lambda _: "XXX"], ) -def test_glibc_version_string_confstr_fail(monkeypatch, failure): +def test_glibc_version_string_confstr_fail(monkeypatch, failure) -> None: monkeypatch.setattr(os, "confstr", failure, raising=False) assert _glibc_version_string_confstr() is None -def test_glibc_version_string_confstr_missing(monkeypatch): +def test_glibc_version_string_confstr_missing(monkeypatch) -> None: monkeypatch.delattr(os, "confstr", raising=False) assert _glibc_version_string_confstr() is None -def test_glibc_version_string_ctypes_missing(monkeypatch): +def test_glibc_version_string_ctypes_missing(monkeypatch) -> None: monkeypatch.setitem(sys.modules, "ctypes", None) assert _glibc_version_string_ctypes() is None @pytest.mark.xfail(ctypes is None, reason="ctypes not available") -def test_glibc_version_string_ctypes_raise_oserror(monkeypatch): +def test_glibc_version_string_ctypes_raise_oserror(monkeypatch) -> None: def patched_cdll(_name): raise OSError("Dynamic loading not supported") @@ -149,18 +153,18 @@ def patched_cdll(_name): @pytest.mark.skipif(platform.system() != "Linux", reason="requires Linux") -def test_is_manylinux_compatible_old(): +def test_is_manylinux_compatible_old() -> None: # Assuming no one is running this test with a version of glibc released in # 1997. assert _is_compatible("any", (2, 0)) -def test_is_manylinux_compatible(monkeypatch): +def test_is_manylinux_compatible(monkeypatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: "2.4") assert _is_compatible("any", (2, 4)) -def test_glibc_version_string_none(monkeypatch): +def test_glibc_version_string_none(monkeypatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: None) assert not _is_compatible("any", (2, 4)) @@ -168,7 +172,7 @@ def test_glibc_version_string_none(monkeypatch): @pytest.mark.parametrize( "content", [None, "invalid-magic", "invalid-class", "invalid-data", "too-short"] ) -def test_parse_elf_bad_executable(content): +def test_parse_elf_bad_executable(content) -> None: if content: path = pathlib.Path(__file__).parent / "manylinux" / f"hello-world-{content}" path = os.fsdecode(path) diff --git a/tests/test_markers.py b/tests/test_markers.py index ad24174f9..7b246223b 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -60,34 +60,34 @@ class TestNode: @pytest.mark.parametrize("value", ["one", "two", None, 3, 5, []]) - def test_accepts_value(self, value): + def test_accepts_value(self, value) -> None: assert Node(value).value == value @pytest.mark.parametrize("value", ["one", "two"]) - def test_str(self, value): + def test_str(self, value) -> None: assert str(Node(value)) == str(value) @pytest.mark.parametrize("value", ["one", "two"]) - def test_repr(self, value): + def test_repr(self, value) -> None: assert repr(Node(value)) == f"" - def test_base_class(self): + def test_base_class(self) -> None: with pytest.raises(NotImplementedError): Node("cover all the code").serialize() class TestOperatorEvaluation: - def test_prefers_pep440(self): + def test_prefers_pep440(self) -> None: assert Marker('"2.7.9" < "foo"').evaluate(dict(foo="2.7.10")) - def test_falls_back_to_python(self): + def test_falls_back_to_python(self) -> None: assert Marker('"b" > "a"').evaluate(dict(a="a")) - def test_fails_when_undefined(self): + def test_fails_when_undefined(self) -> None: with pytest.raises(UndefinedComparison): Marker("'2.7.0' ~= os_name").evaluate() - def test_allows_prerelease(self): + def test_allows_prerelease(self) -> None: assert Marker('python_full_version > "3.6.2"').evaluate( {"python_full_version": "3.11.0a5"} ) @@ -99,7 +99,7 @@ def test_allows_prerelease(self): class TestDefaultEnvironment: - def test_matches_expected(self): + def test_matches_expected(self) -> None: environment = default_environment() iver = ( @@ -127,7 +127,7 @@ def test_matches_expected(self): "sys_platform": sys.platform, } - def test_multidigit_minor_version(self, monkeypatch): + def test_multidigit_minor_version(self, monkeypatch) -> None: version_info = (3, 10, 0, "final", 0) monkeypatch.setattr(sys, "version_info", version_info, raising=False) @@ -139,11 +139,11 @@ def test_multidigit_minor_version(self, monkeypatch): environment = default_environment() assert environment["python_version"] == "3.10" - def tests_when_releaselevel_final(self): + def tests_when_releaselevel_final(self) -> None: v = FakeVersionInfo(3, 4, 2, "final", 0) assert format_full_version(v) == "3.4.2" - def tests_when_releaselevel_not_final(self): + def tests_when_releaselevel_not_final(self) -> None: v = FakeVersionInfo(3, 4, 2, "beta", 4) assert format_full_version(v) == "3.4.2b4" @@ -160,7 +160,7 @@ class TestMarker: for i in itertools.product(VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_valid(self, marker_string): + def test_parses_valid(self, marker_string) -> None: Marker(marker_string) @pytest.mark.parametrize( @@ -174,7 +174,7 @@ def test_parses_valid(self, marker_string): '(python_version == "2.7") with random text', ], ) - def test_parses_invalid(self, marker_string): + def test_parses_invalid(self, marker_string) -> None: with pytest.raises(InvalidMarker): Marker(marker_string) @@ -213,7 +213,7 @@ def test_parses_invalid(self, marker_string): ), ], ) - def test_str_repr_eq_hash(self, marker_string, expected): + def test_str_repr_eq_hash(self, marker_string, expected) -> None: m = Marker(marker_string) assert str(m) == expected assert repr(m) == f"" @@ -248,21 +248,21 @@ def test_str_repr_eq_hash(self, marker_string, expected): ), ], ) - def test_different_markers_different_hashes(self, example1, example2): + def test_different_markers_different_hashes(self, example1, example2) -> None: marker1, marker2 = Marker(example1), Marker(example2) # Markers created from strings that are not equivalent should differ. assert marker1 != marker2 # Different Marker objects should have different hashes. assert hash(marker1) != hash(marker2) - def test_compare_markers_to_other_objects(self): + def test_compare_markers_to_other_objects(self) -> None: # Markers should not be comparable to other kinds of objects. assert Marker("os_name == 'nt'") != "os_name == 'nt'" - def test_environment_assumes_empty_extra(self): + def test_environment_assumes_empty_extra(self) -> None: assert Marker('extra == "im_valid"').evaluate() is False - def test_environment_with_extra_none(self): + def test_environment_with_extra_none(self) -> None: # GIVEN marker_str = 'extra == "im_valid"' @@ -316,7 +316,7 @@ def test_environment_with_extra_none(self): ), ], ) - def test_evaluates(self, marker_string, environment, expected): + def test_evaluates(self, marker_string, environment, expected) -> None: args = [] if environment is None else [environment] assert Marker(marker_string).evaluate(*args) == expected @@ -331,7 +331,7 @@ def test_evaluates(self, marker_string, environment, expected): for i in itertools.product(PEP_345_VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_pep345_valid(self, marker_string): + def test_parses_pep345_valid(self, marker_string) -> None: Marker(marker_string) @pytest.mark.parametrize( @@ -353,7 +353,9 @@ def test_parses_pep345_valid(self, marker_string): ), ], ) - def test_evaluate_pep345_markers(self, marker_string, environment, expected): + def test_evaluate_pep345_markers( + self, marker_string, environment, expected + ) -> None: args = [] if environment is None else [environment] assert Marker(marker_string).evaluate(*args) == expected @@ -368,15 +370,15 @@ def test_evaluate_pep345_markers(self, marker_string, environment, expected): for i in itertools.product(SETUPTOOLS_VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_setuptools_legacy_valid(self, marker_string): + def test_parses_setuptools_legacy_valid(self, marker_string) -> None: Marker(marker_string) - def test_evaluate_setuptools_legacy_markers(self): + def test_evaluate_setuptools_legacy_markers(self) -> None: marker_string = "python_implementation=='Jython'" args = [{"platform_python_implementation": "CPython"}] assert Marker(marker_string).evaluate(*args) is False - def test_extra_str_normalization(self): + def test_extra_str_normalization(self) -> None: raw_name = "S_P__A_M" normalized_name = "s-p-a-m" lhs = f"{raw_name!r} == extra" @@ -385,13 +387,13 @@ def test_extra_str_normalization(self): assert str(Marker(lhs)) == f'"{normalized_name}" == extra' assert str(Marker(rhs)) == f'extra == "{normalized_name}"' - def test_python_full_version_untagged_user_provided(self): + def test_python_full_version_untagged_user_provided(self) -> None: """A user-provided python_full_version ending with a + is also repaired.""" assert Marker("python_full_version < '3.12'").evaluate( {"python_full_version": "3.11.1+"} ) - def test_python_full_version_untagged(self): + def test_python_full_version_untagged(self) -> None: with mock.patch("platform.python_version", return_value="3.11.1+"): assert Marker("python_full_version < '3.12'").evaluate() @@ -412,12 +414,12 @@ def test_python_full_version_untagged(self): pytest.param('"Foo" in {0}', True, id="case-sensitive"), ], ) - def test_extras_and_dependency_groups(self, variable, expression, result): + def test_extras_and_dependency_groups(self, variable, expression, result) -> None: environment = {variable: {"foo", "bar"}} assert Marker(expression.format(variable)).evaluate(environment) == result @pytest.mark.parametrize("variable", ["extras", "dependency_groups"]) - def test_extras_and_dependency_groups_disallowed(self, variable): + def test_extras_and_dependency_groups_disallowed(self, variable) -> None: marker = Marker(f'"foo" in {variable}') assert not marker.evaluate(context="lock_file") diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 36143ce07..4b8dfb23f 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -13,7 +13,7 @@ class TestRawMetadata: @pytest.mark.parametrize("raw_field", sorted(metadata._STRING_FIELDS)) - def test_non_repeating_fields_only_once(self, raw_field): + def test_non_repeating_fields_only_once(self, raw_field) -> None: data = "VaLuE" header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] single_header = f"{header_field}: {data}" @@ -24,7 +24,7 @@ def test_non_repeating_fields_only_once(self, raw_field): assert raw[raw_field] == data @pytest.mark.parametrize("raw_field", sorted(metadata._STRING_FIELDS)) - def test_non_repeating_fields_repeated(self, raw_field): + def test_non_repeating_fields_repeated(self, raw_field) -> None: header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] data = "VaLuE" single_header = f"{header_field}: {data}" @@ -36,7 +36,7 @@ def test_non_repeating_fields_repeated(self, raw_field): assert unparsed[header_field] == [data] * 2 @pytest.mark.parametrize("raw_field", sorted(metadata._LIST_FIELDS)) - def test_repeating_fields_only_once(self, raw_field): + def test_repeating_fields_only_once(self, raw_field) -> None: data = "VaLuE" header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] single_header = f"{header_field}: {data}" @@ -47,7 +47,7 @@ def test_repeating_fields_only_once(self, raw_field): assert raw[raw_field] == [data] @pytest.mark.parametrize("raw_field", sorted(metadata._LIST_FIELDS)) - def test_repeating_fields_repeated(self, raw_field): + def test_repeating_fields_repeated(self, raw_field) -> None: header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] data = "VaLuE" single_header = f"{header_field}: {data}" @@ -71,7 +71,7 @@ def test_repeating_fields_repeated(self, raw_field): ("A B", ["A B"]), ], ) - def test_keywords(self, given, expected): + def test_keywords(self, given, expected) -> None: header = f"Keywords: {given}" raw, unparsed = metadata.parse_email(header) assert not unparsed @@ -91,7 +91,7 @@ def test_keywords(self, given, expected): ("A,B,C", {"A": "B,C"}), ], ) - def test_project_urls_parsing(self, given, expected): + def test_project_urls_parsing(self, given, expected) -> None: header = f"project-url: {given}" raw, unparsed = metadata.parse_email(header) assert not unparsed @@ -99,7 +99,7 @@ def test_project_urls_parsing(self, given, expected): assert "project_urls" in raw assert raw["project_urls"] == expected - def test_duplicate_project_urls(self): + def test_duplicate_project_urls(self) -> None: header = "project-url: A, B\nproject-url: A, C" raw, unparsed = metadata.parse_email(header) assert not raw @@ -107,7 +107,7 @@ def test_duplicate_project_urls(self): assert "project-url" in unparsed assert unparsed["project-url"] == ["A, B", "A, C"] - def test_str_input(self): + def test_str_input(self) -> None: name = "Tarek Ziadé" header = f"author: {name}" raw, unparsed = metadata.parse_email(header) @@ -116,7 +116,7 @@ def test_str_input(self): assert "author" in raw assert raw["author"] == name - def test_bytes_input(self): + def test_bytes_input(self) -> None: name = "Tarek Ziadé" header = f"author: {name}".encode() raw, unparsed = metadata.parse_email(header) @@ -125,7 +125,7 @@ def test_bytes_input(self): assert "author" in raw assert raw["author"] == name - def test_header_mojibake(self): + def test_header_mojibake(self) -> None: value = "\xc0msterdam" header_name = "value" header_bytes = f"{header_name}: {value}".encode("latin1") @@ -139,14 +139,14 @@ def test_header_mojibake(self): assert unparsed[header_name] == [value] @pytest.mark.parametrize("given", ["hello", "description: hello", b"hello"]) - def test_description(self, given): + def test_description(self, given) -> None: raw, unparsed = metadata.parse_email(given) assert not unparsed assert len(raw) == 1 assert "description" in raw assert raw["description"] == "hello" - def test_description_non_utf8(self): + def test_description_non_utf8(self) -> None: header = "\xc0msterdam" header_bytes = header.encode("latin1") raw, unparsed = metadata.parse_email(header_bytes) @@ -163,14 +163,14 @@ def test_description_non_utf8(self): ("description: 1\ndescription: 2\n\n3", ["1", "2", "3"]), ], ) - def test_description_multiple(self, given, expected): + def test_description_multiple(self, given, expected) -> None: raw, unparsed = metadata.parse_email(given) assert not raw assert len(unparsed) == 1 assert "description" in unparsed assert unparsed["description"] == expected - def test_lowercase_keys(self): + def test_lowercase_keys(self) -> None: header = "AUTHOR: Tarek Ziadé\nWhatever: Else" raw, unparsed = metadata.parse_email(header) assert len(raw) == 1 @@ -178,7 +178,7 @@ def test_lowercase_keys(self): assert len(unparsed) == 1 assert "whatever" in unparsed - def test_complete(self): + def test_complete(self) -> None: """Test all fields (except `Obsoletes-Dist`). `Obsoletes-Dist` was sacrificed to provide a value for `Dynamic`. @@ -254,13 +254,13 @@ def test_complete(self): class TestExceptionGroup: - def test_attributes(self): + def test_attributes(self) -> None: individual_exception = Exception("not important") exc = metadata.ExceptionGroup("message", [individual_exception]) assert exc.message == "message" assert list(exc.exceptions) == [individual_exception] - def test_repr(self): + def test_repr(self) -> None: individual_exception = RuntimeError("not important") exc = metadata.ExceptionGroup("message", [individual_exception]) assert individual_exception.__class__.__name__ in repr(exc) @@ -286,7 +286,7 @@ def _invalid_with_cause(self, meta, attr, cause=None, *, field=None): else: assert isinstance(exc.__cause__, cause) - def test_from_email(self): + def test_from_email(self) -> None: metadata_version = "2.5" meta = metadata.Metadata.from_email( f"Metadata-Version: {metadata_version}", validate=False @@ -295,37 +295,37 @@ def test_from_email(self): assert meta.metadata_version == metadata_version assert meta.import_names is None - def test_from_email_empty_import_name(self): + def test_from_email_empty_import_name(self) -> None: meta = metadata.Metadata.from_email( "Metadata-Version: 2.5\nImport-Name:\n", validate=False ) assert meta.import_names == [] - def test_from_email_unparsed(self): + def test_from_email_unparsed(self) -> None: with pytest.raises(ExceptionGroup) as exc_info: metadata.Metadata.from_email("Hello: PyPA") assert len(exc_info.value.exceptions) == 1 assert isinstance(exc_info.value.exceptions[0], metadata.InvalidMetadata) - def test_from_email_validate(self): + def test_from_email_validate(self) -> None: with pytest.raises(ExceptionGroup): # Lacking all required fields. metadata.Metadata.from_email("Name: packaging", validate=True) - def test_from_email_unparsed_valid_field_name(self): + def test_from_email_unparsed_valid_field_name(self) -> None: with pytest.raises(ExceptionGroup): metadata.Metadata.from_email( "Project-URL: A, B\nProject-URL: A, C", validate=True ) - def test_required_fields(self): + def test_required_fields(self) -> None: meta = metadata.Metadata.from_raw(_RAW_EXAMPLE) assert meta.metadata_version == _RAW_EXAMPLE["metadata_version"] @pytest.mark.parametrize("field", list(_RAW_EXAMPLE.keys())) - def test_required_fields_missing(self, field): + def test_required_fields_missing(self, field) -> None: required_fields = _RAW_EXAMPLE.copy() del required_fields[field] @@ -333,7 +333,7 @@ def test_required_fields_missing(self, field): with pytest.raises(ExceptionGroup): metadata.Metadata.from_raw(required_fields) - def test_raw_validate_unrecognized_field(self): + def test_raw_validate_unrecognized_field(self) -> None: raw = { "metadata_version": "2.3", "name": "packaging", @@ -348,19 +348,19 @@ def test_raw_validate_unrecognized_field(self): with pytest.raises(ExceptionGroup): metadata.Metadata.from_raw(raw, validate=True) - def test_raw_data_not_mutated(self): + def test_raw_data_not_mutated(self) -> None: raw = _RAW_EXAMPLE.copy() meta = metadata.Metadata.from_raw(raw, validate=True) assert meta.version == version.Version(_RAW_EXAMPLE["version"]) assert raw == _RAW_EXAMPLE - def test_caching(self): + def test_caching(self) -> None: meta = metadata.Metadata.from_raw(_RAW_EXAMPLE, validate=True) assert meta.version is meta.version - def test_from_raw_validate(self): + def test_from_raw_validate(self) -> None: required_fields = _RAW_EXAMPLE.copy() required_fields["version"] = "-----" @@ -370,7 +370,7 @@ def test_from_raw_validate(self): metadata.Metadata.from_raw(required_fields) @pytest.mark.parametrize("meta_version", ["2.2", "2.3"]) - def test_metadata_version_field_introduction(self, meta_version): + def test_metadata_version_field_introduction(self, meta_version) -> None: raw = { "metadata_version": meta_version, "name": "packaging", @@ -381,7 +381,7 @@ def test_metadata_version_field_introduction(self, meta_version): assert metadata.Metadata.from_raw(raw, validate=True) @pytest.mark.parametrize("meta_version", ["1.0", "1.1", "1.2", "2.1"]) - def test_metadata_version_field_introduction_mismatch(self, meta_version): + def test_metadata_version_field_introduction_mismatch(self, meta_version) -> None: raw = { "metadata_version": meta_version, "name": "packaging", @@ -405,7 +405,7 @@ def test_metadata_version_field_introduction_mismatch(self, meta_version): "license", ], ) - def test_single_value_unvalidated_attribute(self, attribute): + def test_single_value_unvalidated_attribute(self, attribute) -> None: value = "Not important" meta = metadata.Metadata.from_raw({attribute: value}, validate=False) @@ -424,47 +424,47 @@ def test_single_value_unvalidated_attribute(self, attribute): "obsoletes", ], ) - def test_multi_value_unvalidated_attribute(self, attribute): + def test_multi_value_unvalidated_attribute(self, attribute) -> None: values = ["Not important", "Still not important"] meta = metadata.Metadata.from_raw({attribute: values}, validate=False) assert getattr(meta, attribute) == values @pytest.mark.parametrize("version", ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]) - def test_valid_metadata_version(self, version): + def test_valid_metadata_version(self, version) -> None: meta = metadata.Metadata.from_raw({"metadata_version": version}, validate=False) assert meta.metadata_version == version @pytest.mark.parametrize("version", ["1.3", "2.0"]) - def test_invalid_metadata_version(self, version): + def test_invalid_metadata_version(self, version) -> None: meta = metadata.Metadata.from_raw({"metadata_version": version}, validate=False) with pytest.raises(metadata.InvalidMetadata): meta.metadata_version # noqa: B018 - def test_valid_version(self): + def test_valid_version(self) -> None: version_str = "1.2.3" meta = metadata.Metadata.from_raw({"version": version_str}, validate=False) assert meta.version == version.parse(version_str) - def test_missing_version(self): + def test_missing_version(self) -> None: meta = metadata.Metadata.from_raw({}, validate=False) with pytest.raises(metadata.InvalidMetadata) as exc_info: meta.version # noqa: B018 assert exc_info.value.field == "version" - def test_invalid_version(self): + def test_invalid_version(self) -> None: meta = metadata.Metadata.from_raw({"version": "a.b.c"}, validate=False) self._invalid_with_cause(meta, "version", version.InvalidVersion) - def test_valid_summary(self): + def test_valid_summary(self) -> None: summary = "Hello" meta = metadata.Metadata.from_raw({"summary": summary}, validate=False) assert meta.summary == summary - def test_invalid_summary(self): + def test_invalid_summary(self) -> None: meta = metadata.Metadata.from_raw( {"summary": "Hello\n Again"}, validate=False ) @@ -473,12 +473,12 @@ def test_invalid_summary(self): meta.summary # noqa: B018 assert exc_info.value.field == "summary" - def test_valid_name(self): + def test_valid_name(self) -> None: name = "Hello_World" meta = metadata.Metadata.from_raw({"name": name}, validate=False) assert meta.name == name - def test_invalid_name(self): + def test_invalid_name(self) -> None: meta = metadata.Metadata.from_raw({"name": "-not-legal"}, validate=False) self._invalid_with_cause(meta, "name", utils.InvalidName) @@ -497,7 +497,7 @@ def test_invalid_name(self): "text/markdown; variant=CommonMark", ], ) - def test_valid_description_content_type(self, content_type): + def test_valid_description_content_type(self, content_type) -> None: meta = metadata.Metadata.from_raw( {"description_content_type": content_type}, validate=False ) @@ -514,7 +514,7 @@ def test_valid_description_content_type(self, content_type): "text/markdown; variant=commonmark", ], ) - def test_invalid_description_content_type(self, content_type): + def test_invalid_description_content_type(self, content_type) -> None: meta = metadata.Metadata.from_raw( {"description_content_type": content_type}, validate=False ) @@ -522,13 +522,13 @@ def test_invalid_description_content_type(self, content_type): with pytest.raises(metadata.InvalidMetadata): meta.description_content_type # noqa: B018 - def test_keywords(self): + def test_keywords(self) -> None: keywords = ["hello", "world"] meta = metadata.Metadata.from_raw({"keywords": keywords}, validate=False) assert meta.keywords == keywords - def test_valid_project_urls(self): + def test_valid_project_urls(self) -> None: urls = { "Documentation": "https://example.com/BeagleVote", "Bug Tracker": "http://bitbucket.org/tarek/distribute/issues/", @@ -538,7 +538,7 @@ def test_valid_project_urls(self): assert meta.project_urls == urls @pytest.mark.parametrize("specifier", [">=3", ">2.6,!=3.0.*,!=3.1.*", "~=2.6"]) - def test_valid_requires_python(self, specifier): + def test_valid_requires_python(self, specifier) -> None: expected = specifiers.SpecifierSet(specifier) meta = metadata.Metadata.from_raw( {"requires_python": specifier}, validate=False @@ -546,7 +546,7 @@ def test_valid_requires_python(self, specifier): assert meta.requires_python == expected - def test_invalid_requires_python(self): + def test_invalid_requires_python(self) -> None: meta = metadata.Metadata.from_raw( {"requires_python": "NotReal"}, validate=False ) @@ -557,7 +557,7 @@ def test_invalid_requires_python(self): field="requires-python", ) - def test_requires_external(self): + def test_requires_external(self) -> None: externals = [ "C", "libpng (>=1.5)", @@ -570,20 +570,20 @@ def test_requires_external(self): assert meta.requires_external == externals - def test_valid_provides_extra(self): + def test_valid_provides_extra(self) -> None: extras = ["dev", "test"] meta = metadata.Metadata.from_raw({"provides_extra": extras}, validate=False) assert meta.provides_extra == extras - def test_invalid_provides_extra(self): + def test_invalid_provides_extra(self) -> None: extras = ["pdf", "-Not-Valid", "ok"] meta = metadata.Metadata.from_raw({"provides_extra": extras}, validate=False) self._invalid_with_cause( meta, "provides_extra", utils.InvalidName, field="provides-extra" ) - def test_valid_requires_dist(self): + def test_valid_requires_dist(self) -> None: requires = [ "pkginfo", "PasteDeploy", @@ -595,7 +595,7 @@ def test_valid_requires_dist(self): assert meta.requires_dist == expected_requires - def test_invalid_requires_dist(self): + def test_invalid_requires_dist(self) -> None: requires = ["pkginfo", "-not-real", "zope.interface (>3.5.0)"] meta = metadata.Metadata.from_raw({"requires_dist": requires}, validate=False) self._invalid_with_cause( @@ -605,13 +605,13 @@ def test_invalid_requires_dist(self): field="requires-dist", ) - def test_valid_dynamic(self): + def test_valid_dynamic(self) -> None: dynamic = ["Keywords", "Home-Page", "Author"] meta = metadata.Metadata.from_raw({"dynamic": dynamic}, validate=False) assert meta.dynamic == [d.lower() for d in dynamic] - def test_invalid_dynamic_value(self): + def test_invalid_dynamic_value(self) -> None: dynamic = ["Keywords", "NotReal", "Author"] meta = metadata.Metadata.from_raw({"dynamic": dynamic}, validate=False) @@ -619,7 +619,7 @@ def test_invalid_dynamic_value(self): meta.dynamic # noqa: B018 @pytest.mark.parametrize("field_name", ["name", "version", "metadata-version"]) - def test_disallowed_dynamic(self, field_name): + def test_disallowed_dynamic(self, field_name) -> None: meta = metadata.Metadata.from_raw({"dynamic": [field_name]}, validate=False) message = f"{field_name!r} is not allowed" @@ -634,7 +634,7 @@ def test_disallowed_dynamic(self, field_name): "field_name", sorted(metadata._RAW_TO_EMAIL_MAPPING.keys() - metadata._REQUIRED_ATTRS), ) - def test_optional_defaults_to_none(self, field_name): + def test_optional_defaults_to_none(self, field_name) -> None: meta = metadata.Metadata.from_raw({}, validate=False) assert getattr(meta, field_name) is None @@ -705,7 +705,7 @@ def test_optional_defaults_to_none(self, field_name): ("((MIT AND (MIT)))", "((MIT AND (MIT)))"), ], ) - def test_valid_license_expression(self, license_expression, expected): + def test_valid_license_expression(self, license_expression, expected) -> None: meta = metadata.Metadata.from_raw( {"license_expression": license_expression}, validate=False ) @@ -745,7 +745,7 @@ def test_valid_license_expression(self, license_expression, expected): "mit with ( ) with ( ) or mit", ], ) - def test_invalid_license_expression(self, license_expression): + def test_invalid_license_expression(self, license_expression) -> None: meta = metadata.Metadata.from_raw( {"license_expression": license_expression}, validate=False ) @@ -761,7 +761,7 @@ def test_invalid_license_expression(self, license_expression): ["LICENSE"], ], ) - def test_valid_license_files(self, license_files): + def test_valid_license_files(self, license_files) -> None: meta = metadata.Metadata.from_raw( {"license_files": license_files}, validate=False ) @@ -784,7 +784,7 @@ def test_valid_license_files(self, license_files): ["licenses\\LICENSE"], ], ) - def test_invalid_license_files(self, license_files): + def test_invalid_license_files(self, license_files) -> None: meta = metadata.Metadata.from_raw( {"license_files": license_files}, validate=False ) @@ -793,7 +793,7 @@ def test_invalid_license_files(self, license_files): meta.license_files # noqa: B018 @pytest.mark.parametrize("key", ["import_namespaces", "import_names"]) - def test_valid_import_names(self, key): + def test_valid_import_names(self, key) -> None: import_names = [ "packaging", "packaging.metadata", @@ -808,14 +808,14 @@ def test_valid_import_names(self, key): @pytest.mark.parametrize( "name", ["not-valid", "still.not-valid", "stuff;", "stuff; extra"] ) - def test_invalid_import_names_identifier(self, key, name): + def test_invalid_import_names_identifier(self, key, name) -> None: meta = metadata.Metadata.from_raw({key: [name]}, validate=False) with pytest.raises(metadata.InvalidMetadata): getattr(meta, key) @pytest.mark.parametrize("key", ["import_namespaces", "import_names"]) - def test_invalid_import_names_keyword(self, key): + def test_invalid_import_names_keyword(self, key) -> None: import_names = ["class"] meta = metadata.Metadata.from_raw({key: import_names}, validate=False) @@ -824,14 +824,14 @@ def test_invalid_import_names_keyword(self, key): class TestMetadataWriting: - def test_write_metadata(self): + def test_write_metadata(self) -> None: meta = metadata.Metadata.from_raw(_RAW_EXAMPLE) written = meta.as_rfc822().as_string() assert ( written == "metadata-version: 2.5\nname: packaging\nversion: 2023.0.0\n\n" ) - def test_write_metadata_with_description(self): + def test_write_metadata_with_description(self) -> None: # Intentionally out of order to make sure it is written in order meta = metadata.Metadata.from_raw( { @@ -853,7 +853,7 @@ def test_write_metadata_with_description(self): "version: 1.2.3\n\nHello\n\nWorld👋".encode() ) - def test_multiline_license(self): + def test_multiline_license(self) -> None: meta = metadata.Metadata.from_raw( { "version": "1.2.3", @@ -874,7 +874,7 @@ def test_multiline_license(self): "\nlicense: Hello\n World🐍\n\n".encode() ) - def test_large(self): + def test_large(self) -> None: meta = metadata.Metadata.from_raw( { "author": "Example!", @@ -952,7 +952,7 @@ def test_large(self): assert core_metadata.get_payload() == "some readme 👋\n" - def test_modern_license(self): + def test_modern_license(self) -> None: meta = metadata.Metadata.from_raw( { "metadata_version": "2.4", @@ -975,7 +975,7 @@ def test_modern_license(self): assert core_metadata.get_payload() is None - def test__import_names(self): + def test__import_names(self) -> None: meta = metadata.Metadata.from_raw( { "metadata_version": "2.5", @@ -998,7 +998,7 @@ def test__import_names(self): assert core_metadata.get_payload() is None - def test_empty_import_names(self): + def test_empty_import_names(self) -> None: meta = metadata.Metadata.from_raw( { "metadata_version": "2.5", diff --git a/tests/test_musllinux.py b/tests/test_musllinux.py index a62deb822..5615faefa 100644 --- a/tests/test_musllinux.py +++ b/tests/test_musllinux.py @@ -43,7 +43,7 @@ def clear_lru_cache(): ], ids=["amd64-1.2.2", "i386-1.2.1", "aarch64-1.1.24", "invalid", "unknown"], ) -def test_parse_musl_version(output, version): +def test_parse_musl_version(output, version) -> None: assert _parse_musl_version(output) == version @@ -58,7 +58,7 @@ def test_parse_musl_version(output, version): ], ids=["does-not-exist", "glibc", "x86_64", "i386", "aarch64"], ) -def test_get_musl_version(monkeypatch, executable, output, version, ld_musl): +def test_get_musl_version(monkeypatch, executable, output, version, ld_musl) -> None: def mock_run(*args, **kwargs): return collections.namedtuple("Proc", "stderr")(output) diff --git a/tests/test_specifiers.py b/tests/test_specifiers.py index ff2a04366..f20b9f2fa 100644 --- a/tests/test_specifiers.py +++ b/tests/test_specifiers.py @@ -37,7 +37,7 @@ class TestSpecifier: @pytest.mark.parametrize("specifier", SPECIFIERS) - def test_specifiers_valid(self, specifier): + def test_specifiers_valid(self, specifier) -> None: Specifier(specifier) @pytest.mark.parametrize( @@ -84,7 +84,7 @@ def test_specifiers_valid(self, specifier): "!=1.0.dev1.*", ], ) - def test_specifiers_invalid(self, specifier): + def test_specifiers_invalid(self, specifier) -> None: with pytest.raises(InvalidSpecifier): Specifier(specifier) @@ -196,7 +196,7 @@ def test_specifiers_invalid(self, specifier): " \r \f \v v1.0\t\n", ], ) - def test_specifiers_normalized(self, version): + def test_specifiers_normalized(self, version) -> None: if "+" not in version: ops = ["~=", "==", "!=", "<=", ">=", "<", ">"] else: @@ -220,14 +220,14 @@ def test_specifiers_normalized(self, version): ("< 2", "<2"), ], ) - def test_specifiers_str_and_repr(self, specifier, expected): + def test_specifiers_str_and_repr(self, specifier, expected) -> None: spec = Specifier(specifier) assert str(spec) == expected assert repr(spec) == f"" @pytest.mark.parametrize("specifier", SPECIFIERS) - def test_specifiers_hash(self, specifier): + def test_specifiers_hash(self, specifier) -> None: assert hash(Specifier(specifier)) == hash(Specifier(specifier)) @pytest.mark.parametrize( @@ -243,13 +243,13 @@ def test_specifiers_hash(self, specifier): ] ), ) - def test_comparison_true(self, left, right, op): + def test_comparison_true(self, left, right, op) -> None: assert op(Specifier(left), Specifier(right)) assert op(left, Specifier(right)) assert op(Specifier(left), right) @pytest.mark.parametrize(("left", "right"), [("==2.8.0", "==2.8")]) - def test_comparison_canonicalizes(self, left, right): + def test_comparison_canonicalizes(self, left, right) -> None: assert Specifier(left) == Specifier(right) assert left == Specifier(right) assert Specifier(left) == right @@ -267,12 +267,12 @@ def test_comparison_canonicalizes(self, left, right): ] ), ) - def test_comparison_false(self, left, right, op): + def test_comparison_false(self, left, right, op) -> None: assert not op(Specifier(left), Specifier(right)) assert not op(left, Specifier(right)) assert not op(Specifier(left), right) - def test_comparison_non_specifier(self): + def test_comparison_non_specifier(self) -> None: assert Specifier("==1.0") != 12 assert not Specifier("==1.0") == 12 assert Specifier("==1.0") != "12" @@ -475,7 +475,7 @@ def test_comparison_non_specifier(self): ] ], ) - def test_specifiers(self, version, spec, expected): + def test_specifiers(self, version, spec, expected) -> None: spec = Specifier(spec, prereleases=True) if expected: @@ -502,7 +502,7 @@ def test_specifiers(self, version, spec, expected): ("===invalid", "invalid"), ], ) - def test_invalid_spec(self, spec, version): + def test_invalid_spec(self, spec, version) -> None: spec = Specifier(spec, prereleases=True) assert not spec.contains(version) @@ -572,7 +572,7 @@ def test_specifier_prereleases_set( ("1.0.dev0", "===1.0.dev0", True), ], ) - def test_specifiers_identity(self, version, spec, expected): + def test_specifiers_identity(self, version, spec, expected) -> None: spec = Specifier(spec) if expected: @@ -601,7 +601,7 @@ def test_specifiers_identity(self, version, spec, expected): ("~=1.0.dev1", True), ], ) - def test_specifier_prereleases_detection(self, specifier, expected): + def test_specifier_prereleases_detection(self, specifier, expected) -> None: assert Specifier(specifier).prereleases == expected @pytest.mark.parametrize( @@ -687,7 +687,7 @@ def test_specifier_filter( ("===lolwat", "==="), ], ) - def test_specifier_operator_property(self, spec, op): + def test_specifier_operator_property(self, spec, op) -> None: assert Specifier(spec).operator == op @pytest.mark.parametrize( @@ -706,14 +706,14 @@ def test_specifier_operator_property(self, spec, op): ("===lolwat", "lolwat"), ], ) - def test_specifier_version_property(self, spec, version): + def test_specifier_version_property(self, spec, version) -> None: assert Specifier(spec).version == version @pytest.mark.parametrize( ("spec", "expected_length"), [("", 0), ("==2.0", 1), (">=2.0", 1), (">=2.0,<3", 2), (">=2.0,<3,==2.4", 3)], ) - def test_length(self, spec, expected_length): + def test_length(self, spec, expected_length) -> None: spec = SpecifierSet(spec) assert len(spec) == expected_length @@ -727,21 +727,21 @@ def test_length(self, spec, expected_length): (">=2.0,<3,==2.4", [">=2.0", "<3", "==2.4"]), ], ) - def test_iteration(self, spec, expected_items): + def test_iteration(self, spec, expected_items) -> None: spec = SpecifierSet(spec) items = {str(item) for item in spec} assert items == set(expected_items) - def test_specifier_equal_for_compatible_operator(self): + def test_specifier_equal_for_compatible_operator(self) -> None: assert Specifier("~=1.18.0") != Specifier("~=1.18") - def test_specifier_hash_for_compatible_operator(self): + def test_specifier_hash_for_compatible_operator(self) -> None: assert hash(Specifier("~=1.18.0")) != hash(Specifier("~=1.18")) class TestSpecifierSet: @pytest.mark.parametrize("version", VERSIONS) - def test_empty_specifier(self, version): + def test_empty_specifier(self, version) -> None: spec = SpecifierSet(prereleases=True) assert version in spec @@ -749,7 +749,7 @@ def test_empty_specifier(self, version): assert parse(version) in spec assert spec.contains(parse(version)) - def test_create_from_specifiers(self): + def test_create_from_specifiers(self) -> None: spec_strs = [">=1.0", "!=1.1", "!=1.2", "<2.0"] specs = [Specifier(s) for s in spec_strs] spec = SpecifierSet(iter(specs)) @@ -820,7 +820,7 @@ def test_specifier_prereleases_explicit( assert (version in spec) == final_contains assert spec.contains(version) == final_contains - def test_specifier_contains_prereleases(self): + def test_specifier_contains_prereleases(self) -> None: spec = SpecifierSet() assert spec.prereleases is None assert spec.contains("1.0.dev1") @@ -1208,7 +1208,9 @@ def test_specifier_filter( ), ], ) - def test_filter_exclusionary_bridges(self, specifier, prereleases, input, expected): + def test_filter_exclusionary_bridges( + self, specifier, prereleases, input, expected + ) -> None: """ Test that filter correctly handles exclusionary bridges. @@ -1351,7 +1353,7 @@ def test_contains_exclusionary_bridges( (">=1.0", "not a valid version"), ], ) - def test_contains_rejects_invalid_specifier(self, specifier, input): + def test_contains_rejects_invalid_specifier(self, specifier, input) -> None: spec = SpecifierSet(specifier, prereleases=True) assert not spec.contains(input) @@ -1373,20 +1375,20 @@ def test_contains_rejects_invalid_specifier(self, specifier, input): ("!=2.0 ,>1.0", "!=2.0,>1.0"), ], ) - def test_specifiers_str_and_repr(self, specifier, expected): + def test_specifiers_str_and_repr(self, specifier, expected) -> None: spec = SpecifierSet(specifier) assert str(spec) == expected assert repr(spec) == f"" @pytest.mark.parametrize("specifier", SPECIFIERS + LEGACY_SPECIFIERS) - def test_specifiers_hash(self, specifier): + def test_specifiers_hash(self, specifier) -> None: assert hash(SpecifierSet(specifier)) == hash(SpecifierSet(specifier)) @pytest.mark.parametrize( ("left", "right", "expected"), [(">2.0", "<5.0", ">2.0,<5.0")] ) - def test_specifiers_combine(self, left, right, expected): + def test_specifiers_combine(self, left, right, expected) -> None: result = SpecifierSet(left) & SpecifierSet(right) assert result == SpecifierSet(expected) @@ -1441,7 +1443,7 @@ def test_specifiers_combine(self, left, right, expected): right, prereleases=True ) - def test_specifiers_combine_not_implemented(self): + def test_specifiers_combine_not_implemented(self) -> None: with pytest.raises(TypeError): SpecifierSet() & 12 @@ -1458,7 +1460,7 @@ def test_specifiers_combine_not_implemented(self): ] ), ) - def test_comparison_true(self, left, right, op): + def test_comparison_true(self, left, right, op) -> None: assert op(SpecifierSet(left), SpecifierSet(right)) assert op(SpecifierSet(left), Specifier(right)) assert op(Specifier(left), SpecifierSet(right)) @@ -1478,7 +1480,7 @@ def test_comparison_true(self, left, right, op): ] ), ) - def test_comparison_false(self, left, right, op): + def test_comparison_false(self, left, right, op) -> None: assert not op(SpecifierSet(left), SpecifierSet(right)) assert not op(SpecifierSet(left), Specifier(right)) assert not op(Specifier(left), SpecifierSet(right)) @@ -1486,12 +1488,12 @@ def test_comparison_false(self, left, right, op): assert not op(SpecifierSet(left), right) @pytest.mark.parametrize(("left", "right"), [("==2.8.0", "==2.8")]) - def test_comparison_canonicalizes(self, left, right): + def test_comparison_canonicalizes(self, left, right) -> None: assert SpecifierSet(left) == SpecifierSet(right) assert left == SpecifierSet(right) assert SpecifierSet(left) == right - def test_comparison_non_specifier(self): + def test_comparison_non_specifier(self) -> None: assert SpecifierSet("==1.0") != 12 assert not SpecifierSet("==1.0") == 12 @@ -1506,10 +1508,10 @@ def test_comparison_non_specifier(self): ("1.0.0+local", ">1.0.0", False), ], ) - def test_comparison_ignores_local(self, version, specifier, expected): + def test_comparison_ignores_local(self, version, specifier, expected) -> None: assert (Version(version) in SpecifierSet(specifier)) == expected - def test_contains_with_compatible_operator(self): + def test_contains_with_compatible_operator(self) -> None: combination = SpecifierSet("~=1.18.0") & SpecifierSet("~=1.18") assert "1.19.5" not in combination assert "1.18.0" in combination diff --git a/tests/test_structures.py b/tests/test_structures.py index cc651cf60..3665d97f3 100644 --- a/tests/test_structures.py +++ b/tests/test_structures.py @@ -7,24 +7,24 @@ from packaging._structures import Infinity, NegativeInfinity -def test_infinity_repr(): +def test_infinity_repr() -> None: assert repr(Infinity) == "Infinity" -def test_negative_infinity_repr(): +def test_negative_infinity_repr() -> None: assert repr(NegativeInfinity) == "-Infinity" -def test_infinity_hash(): +def test_infinity_hash() -> None: assert hash(Infinity) == hash(Infinity) -def test_negative_infinity_hash(): +def test_negative_infinity_hash() -> None: assert hash(NegativeInfinity) == hash(NegativeInfinity) @pytest.mark.parametrize("left", [1, "a", ("b", 4)]) -def test_infinity_comparison(left): +def test_infinity_comparison(left) -> None: assert left < Infinity assert left <= Infinity assert not left == Infinity @@ -34,7 +34,7 @@ def test_infinity_comparison(left): @pytest.mark.parametrize("left", [1, "a", ("b", 4)]) -def test_negative_infinity_lesser(left): +def test_negative_infinity_lesser(left) -> None: assert not left < NegativeInfinity assert not left <= NegativeInfinity assert not left == NegativeInfinity @@ -43,17 +43,17 @@ def test_negative_infinity_lesser(left): assert left >= NegativeInfinity -def test_infinity_equal(): +def test_infinity_equal() -> None: assert Infinity == Infinity -def test_negative_infinity_equal(): +def test_negative_infinity_equal() -> None: assert NegativeInfinity == NegativeInfinity -def test_negate_infinity(): +def test_negate_infinity() -> None: assert isinstance(-Infinity, NegativeInfinity.__class__) -def test_negate_negative_infinity(): +def test_negate_negative_infinity() -> None: assert isinstance(-NegativeInfinity, Infinity.__class__) diff --git a/tests/test_tags.py b/tests/test_tags.py index 9212d0245..74a14af8d 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -96,51 +96,51 @@ def mock_android(monkeypatch): class TestTag: - def test_lowercasing(self): + def test_lowercasing(self) -> None: tag = tags.Tag("PY3", "None", "ANY") assert tag.interpreter == "py3" assert tag.abi == "none" assert tag.platform == "any" - def test_equality(self): + def test_equality(self) -> None: args = "py3", "none", "any" assert tags.Tag(*args) == tags.Tag(*args) - def test_equality_fails_with_non_tag(self): + def test_equality_fails_with_non_tag(self) -> None: assert not tags.Tag("py3", "none", "any") == "non-tag" - def test_hashing(self, example_tag): + def test_hashing(self, example_tag) -> None: tags = {example_tag} # Should not raise TypeError. assert example_tag in tags - def test_hash_equality(self, example_tag): + def test_hash_equality(self, example_tag) -> None: equal_tag = tags.Tag("py3", "none", "any") assert example_tag == equal_tag # Sanity check. assert example_tag.__hash__() == equal_tag.__hash__() - def test_str(self, example_tag): + def test_str(self, example_tag) -> None: assert str(example_tag) == "py3-none-any" - def test_repr(self, example_tag): + def test_repr(self, example_tag) -> None: assert repr(example_tag) == f"" - def test_attribute_access(self, example_tag): + def test_attribute_access(self, example_tag) -> None: assert example_tag.interpreter == "py3" assert example_tag.abi == "none" assert example_tag.platform == "any" class TestParseTag: - def test_simple(self, example_tag): + def test_simple(self, example_tag) -> None: parsed_tags = tags.parse_tag(str(example_tag)) assert parsed_tags == {example_tag} - def test_multi_interpreter(self, example_tag): + def test_multi_interpreter(self, example_tag) -> None: expected = {example_tag, tags.Tag("py2", "none", "any")} given = tags.parse_tag("py2.py3-none-any") assert given == expected - def test_multi_platform(self): + def test_multi_platform(self) -> None: expected = { tags.Tag("cp37", "cp37m", platform) for platform in ( @@ -159,7 +159,7 @@ def test_multi_platform(self): class TestInterpreterName: - def test_sys_implementation_name(self, monkeypatch): + def test_sys_implementation_name(self, monkeypatch) -> None: class MockImplementation: pass @@ -168,13 +168,13 @@ class MockImplementation: monkeypatch.setattr(sys, "implementation", mock_implementation, raising=False) assert tags.interpreter_name() == "sillywalk" - def test_interpreter_short_names(self, mock_interpreter_name): + def test_interpreter_short_names(self, mock_interpreter_name) -> None: mock_interpreter_name("cpython") assert tags.interpreter_name() == "cp" class TestInterpreterVersion: - def test_warn(self, monkeypatch): + def test_warn(self, monkeypatch) -> None: class MockConfigVar: def __init__(self, return_): self.warn = None @@ -189,7 +189,7 @@ def __call__(self, _name, warn): tags.interpreter_version(warn=True) assert mock_config_var.warn - def test_python_version_nodot(self, monkeypatch): + def test_python_version_nodot(self, monkeypatch) -> None: monkeypatch.setattr(tags, "_get_config_var", lambda _var, warn: "NN") # noqa: ARG005 assert tags.interpreter_version() == "NN" @@ -203,7 +203,7 @@ def test_python_version_nodot(self, monkeypatch): ((1, 2, 13), "12"), ], ) - def test_sys_version_info(self, version_info, version_str, monkeypatch): + def test_sys_version_info(self, version_info, version_str, monkeypatch) -> None: monkeypatch.setattr(tags, "_get_config_var", lambda *args, **kwargs: None) monkeypatch.setattr(sys, "version_info", version_info) assert tags.interpreter_version() == version_str @@ -221,7 +221,7 @@ class TestMacOSPlatforms: ("ppc64", True, "ppc"), ], ) - def test_architectures(self, arch, is_32bit, expected): + def test_architectures(self, arch, is_32bit, expected) -> None: assert tags._mac_arch(arch, is_32bit=is_32bit) == expected @pytest.mark.parametrize( @@ -263,10 +263,10 @@ def test_architectures(self, arch, is_32bit, expected): ((12, 0), "arm64", ["arm64", "universal2"]), ], ) - def test_binary_formats(self, version, arch, expected): + def test_binary_formats(self, version, arch, expected) -> None: assert tags._mac_binary_formats(version, arch) == expected - def test_version_detection(self, monkeypatch): + def test_version_detection(self, monkeypatch) -> None: if platform.system() != "Darwin": monkeypatch.setattr( platform, "mac_ver", lambda: ("10.14", ("", "", ""), "x86_64") @@ -286,7 +286,7 @@ def test_version_detection(self, monkeypatch): expected = f"macosx_{major}_{minor}_" assert platforms[0].startswith(expected) - def test_version_detection_10_15(self, monkeypatch): + def test_version_detection_10_15(self, monkeypatch) -> None: monkeypatch.setattr( platform, "mac_ver", lambda: ("10.15", ("", "", ""), "x86_64") ) @@ -295,7 +295,7 @@ def test_version_detection_10_15(self, monkeypatch): platforms = list(tags.mac_platforms(arch="x86_64")) assert platforms[0].startswith(expected) - def test_version_detection_compatibility(self, monkeypatch): + def test_version_detection_compatibility(self, monkeypatch) -> None: if platform.system() != "Darwin": monkeypatch.setattr( subprocess, @@ -313,7 +313,7 @@ def test_version_detection_compatibility(self, monkeypatch): assert not platforms[0].startswith(unexpected) @pytest.mark.parametrize("arch", ["x86_64", "i386"]) - def test_arch_detection(self, arch, monkeypatch): + def test_arch_detection(self, arch, monkeypatch) -> None: if platform.system() != "Darwin" or platform.mac_ver()[2] != arch: monkeypatch.setattr( platform, "mac_ver", lambda: ("10.14", ("", "", ""), arch) @@ -321,7 +321,7 @@ def test_arch_detection(self, arch, monkeypatch): monkeypatch.setattr(tags, "_mac_arch", lambda *args: arch) assert next(tags.mac_platforms((10, 14))).endswith(arch) - def test_mac_platforms(self): + def test_mac_platforms(self) -> None: platforms = list(tags.mac_platforms((10, 5), "x86_64")) assert platforms == [ "macosx_10_5_x86_64", @@ -343,7 +343,7 @@ def test_mac_platforms(self): assert not list(tags.mac_platforms((10, 0), "x86_64")) @pytest.mark.parametrize(("major", "minor"), [(11, 0), (11, 3), (12, 0), (12, 3)]) - def test_macos_11(self, major, minor): + def test_macos_11(self, major, minor) -> None: platforms = list(tags.mac_platforms((major, minor), "x86_64")) assert "macosx_11_0_arm64" not in platforms assert "macosx_11_0_x86_64" in platforms @@ -379,7 +379,7 @@ def test_macos_11(self, major, minor): class TestIOSPlatforms: @pytest.mark.usefixtures("mock_ios") - def test_version_detection(self): + def test_version_detection(self) -> None: platforms = list(tags.ios_platforms(multiarch="arm64-iphoneos")) assert platforms == [ "ios_13_2_arm64_iphoneos", @@ -398,12 +398,12 @@ def test_version_detection(self): ] @pytest.mark.usefixtures("mock_ios") - def test_multiarch_detection(self): + def test_multiarch_detection(self) -> None: platforms = list(tags.ios_platforms(version=(12, 0))) assert platforms == ["ios_12_0_gothic_iphoneos"] @pytest.mark.usefixtures("mock_ios") - def test_ios_platforms(self): + def test_ios_platforms(self) -> None: # Pre-iOS 12.0 releases won't match anything platforms = list(tags.ios_platforms((7, 0), "arm64-iphoneos")) assert platforms == [] @@ -459,7 +459,7 @@ def test_ios_platforms(self): class TestAndroidPlatforms: - def test_non_android(self): + def test_non_android(self) -> None: non_android_error = pytest.raises(TypeError) with non_android_error: list(tags.android_platforms()) @@ -477,7 +477,7 @@ def test_non_android(self): ] @pytest.mark.usefixtures("mock_android") - def test_detection(self): + def test_detection(self) -> None: assert list(tags.android_platforms()) == [ "android_21_arm64_v8a", "android_20_arm64_v8a", @@ -487,7 +487,7 @@ def test_detection(self): "android_16_arm64_v8a", ] - def test_api_level(self): + def test_api_level(self) -> None: # API levels below the minimum should return nothing. assert list(tags.android_platforms(api_level=14, abi="x86")) == [] assert list(tags.android_platforms(api_level=15, abi="x86")) == [] @@ -505,7 +505,7 @@ def test_api_level(self): "android_16_x86", ] - def test_abi(self): + def test_abi(self) -> None: # Real ABI, normalized. assert list(tags.android_platforms(api_level=16, abi="armeabi_v7a")) == [ "android_16_armeabi_v7a", @@ -527,13 +527,13 @@ def teardown_method(self): # Clear the version cache tags._manylinux._get_glibc_version.cache_clear() - def test_get_config_var_does_not_log(self, monkeypatch): + def test_get_config_var_does_not_log(self, monkeypatch) -> None: debug = pretend.call_recorder(lambda *a: None) monkeypatch.setattr(tags.logger, "debug", debug) tags._get_config_var("missing") assert debug.calls == [] - def test_get_config_var_does_log(self, monkeypatch): + def test_get_config_var_does_log(self, monkeypatch) -> None: debug = pretend.call_recorder(lambda *a: None) monkeypatch.setattr(tags.logger, "debug", debug) tags._get_config_var("missing", warn=True) @@ -564,14 +564,14 @@ def test_linux_platforms_32_64bit_on_64bit_os( ] assert linux_platform == expected - def test_linux_platforms_manylinux_unsupported(self, monkeypatch): + def test_linux_platforms_manylinux_unsupported(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) linux_platform = list(tags._linux_platforms(is_32bit=False)) assert linux_platform == ["linux_x86_64"] - def test_linux_platforms_manylinux1(self, monkeypatch): + def test_linux_platforms_manylinux1(self, monkeypatch) -> None: monkeypatch.setattr( tags._manylinux, "_is_compatible", @@ -587,7 +587,7 @@ def test_linux_platforms_manylinux1(self, monkeypatch): "linux_x86_64", ] - def test_linux_platforms_manylinux2010(self, monkeypatch): + def test_linux_platforms_manylinux2010(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.12", raising=False) @@ -607,7 +607,7 @@ def test_linux_platforms_manylinux2010(self, monkeypatch): ] assert platforms == expected - def test_linux_platforms_manylinux2014(self, monkeypatch): + def test_linux_platforms_manylinux2014(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.17", raising=False) @@ -665,7 +665,7 @@ def test_linux_platforms_manylinux2014_armhf_abi( expected.extend(f"linux_{arch}" for arch in archs) assert platforms == expected - def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch): + def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch) -> None: monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.17") monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr( @@ -699,7 +699,7 @@ def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch): ] assert platforms == expected - def test_linux_platforms_manylinux_glibc3(self, monkeypatch): + def test_linux_platforms_manylinux_glibc3(self, monkeypatch) -> None: # test for a future glic 3.x version monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "3.2") monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: True) @@ -760,7 +760,7 @@ def test_linux_platforms_musllinux( assert recorder.calls == [pretend.call(fake_executable)] - def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch): + def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch) -> None: monkeypatch.setattr( tags._manylinux, "_is_compatible", @@ -794,7 +794,7 @@ def test_linux_platforms_not_manylinux_abi( expected = [f"linux_{alt_machine}"] assert platforms == expected - def test_linux_not_linux(self, monkeypatch): + def test_linux_not_linux(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "not_linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.17", raising=False) @@ -812,14 +812,14 @@ def test_linux_not_linux(self, monkeypatch): ("Generic", "_generic_platforms"), ], ) -def test_platform_tags(platform_name, dispatch_func, monkeypatch): +def test_platform_tags(platform_name, dispatch_func, monkeypatch) -> None: expected = ["sillywalk"] monkeypatch.setattr(platform, "system", lambda: platform_name) monkeypatch.setattr(tags, dispatch_func, lambda: expected) assert tags.platform_tags() == expected -def test_platform_tags_space(monkeypatch): +def test_platform_tags_space(monkeypatch) -> None: """Ensure spaces in platform tags are normalized to underscores.""" monkeypatch.setattr(platform, "system", lambda: "Isilon OneFS") monkeypatch.setattr(sysconfig, "get_platform", lambda: "isilon onefs") @@ -831,7 +831,7 @@ class TestCPythonABI: ("py_debug", "gettotalrefcount", "result"), [(1, False, True), (0, False, False), (None, True, True)], ) - def test_debug(self, py_debug, gettotalrefcount, result, monkeypatch): + def test_debug(self, py_debug, gettotalrefcount, result, monkeypatch) -> None: config = {"Py_DEBUG": py_debug, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) if gettotalrefcount: @@ -839,7 +839,7 @@ def test_debug(self, py_debug, gettotalrefcount, result, monkeypatch): expected = ["cp37d" if result else "cp37"] assert tags._cpython_abis((3, 7)) == expected - def test_debug_file_extension(self, monkeypatch): + def test_debug_file_extension(self, monkeypatch) -> None: config = {"Py_DEBUG": None} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) monkeypatch.delattr(sys, "gettotalrefcount", raising=False) @@ -849,7 +849,7 @@ def test_debug_file_extension(self, monkeypatch): @pytest.mark.parametrize( ("debug", "expected"), [(True, ["cp38d", "cp38"]), (False, ["cp38"])] ) - def test__debug_cp38(self, debug, expected, monkeypatch): + def test__debug_cp38(self, debug, expected, monkeypatch) -> None: config = {"Py_DEBUG": debug} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._cpython_abis((3, 8)) == expected @@ -863,7 +863,7 @@ def test__debug_cp38(self, debug, expected, monkeypatch): (1, (3, 8), False), ], ) - def test_pymalloc(self, pymalloc, version, result, monkeypatch): + def test_pymalloc(self, pymalloc, version, result, monkeypatch) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": pymalloc, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) base_abi = f"cp{version[0]}{version[1]}" @@ -880,7 +880,9 @@ def test_pymalloc(self, pymalloc, version, result, monkeypatch): (4, 0x10FFFF, (3, 3), False), ], ) - def test_wide_unicode(self, unicode_size, maxunicode, version, result, monkeypatch): + def test_wide_unicode( + self, unicode_size, maxunicode, version, result, monkeypatch + ) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": unicode_size} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) monkeypatch.setattr(sys, "maxunicode", maxunicode) @@ -890,13 +892,13 @@ def test_wide_unicode(self, unicode_size, maxunicode, version, result, monkeypat class TestCPythonTags: - def test_iterator_returned(self): + def test_iterator_returned(self) -> None: result_iterator = tags.cpython_tags( (3, 8), ["cp38d", "cp38"], ["plat1", "plat2"] ) assert isinstance(result_iterator, collections.abc.Iterator) - def test_all_args(self): + def test_all_args(self) -> None: result_iterator = tags.cpython_tags( (3, 11), ["cp311d", "cp311"], ["plat1", "plat2"] ) @@ -976,58 +978,58 @@ def test_all_args(self): tags.Tag("cp313", "none", "plat2"), ] - def test_python_version_defaults(self): + def test_python_version_defaults(self) -> None: tag = next(tags.cpython_tags(abis=["abi3"], platforms=["any"])) interpreter = "cp" + tags._version_nodot(sys.version_info[:2]) assert interpreter == tag.interpreter - def test_abi_defaults(self, monkeypatch): + def test_abi_defaults(self, monkeypatch) -> None: monkeypatch.setattr(tags, "_cpython_abis", lambda _1, _2: ["cp38"]) result = list(tags.cpython_tags((3, 8), platforms=["any"])) assert tags.Tag("cp38", "cp38", "any") in result assert tags.Tag("cp38", "abi3", "any") in result assert tags.Tag("cp38", "none", "any") in result - def test_abi_defaults_needs_underscore(self, monkeypatch): + def test_abi_defaults_needs_underscore(self, monkeypatch) -> None: monkeypatch.setattr(tags, "_cpython_abis", lambda _1, _2: ["cp311"]) result = list(tags.cpython_tags((3, 11), platforms=["any"])) assert tags.Tag("cp311", "cp311", "any") in result assert tags.Tag("cp311", "abi3", "any") in result assert tags.Tag("cp311", "none", "any") in result - def test_platforms_defaults(self, monkeypatch): + def test_platforms_defaults(self, monkeypatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat1"]) result = list(tags.cpython_tags((3, 8), abis=["whatever"])) assert tags.Tag("cp38", "whatever", "plat1") in result - def test_platforms_defaults_needs_underscore(self, monkeypatch): + def test_platforms_defaults_needs_underscore(self, monkeypatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat1"]) result = list(tags.cpython_tags((3, 11), abis=["whatever"])) assert tags.Tag("cp311", "whatever", "plat1") in result - def test_platform_name_space_normalization(self, monkeypatch): + def test_platform_name_space_normalization(self, monkeypatch) -> None: """Ensure that spaces are translated to underscores in platform names.""" monkeypatch.setattr(sysconfig, "get_platform", lambda: "isilon onefs") for tag in tags.cpython_tags(): assert " " not in tag.platform - def test_major_only_python_version(self): + def test_major_only_python_version(self) -> None: result = list(tags.cpython_tags((3,), ["abi"], ["plat"])) assert result == [ tags.Tag("cp3", "abi", "plat"), tags.Tag("cp3", "none", "plat"), ] - def test_major_only_python_version_with_default_abis(self): + def test_major_only_python_version_with_default_abis(self) -> None: result = list(tags.cpython_tags((3,), platforms=["plat"])) assert result == [tags.Tag("cp3", "none", "plat")] @pytest.mark.parametrize("abis", [[], ["abi3"], ["none"]]) - def test_skip_redundant_abis(self, abis): + def test_skip_redundant_abis(self, abis) -> None: results = list(tags.cpython_tags((3, 0), abis=abis, platforms=["any"])) assert results == [tags.Tag("cp30", "none", "any")] - def test_abi3_python33(self): + def test_abi3_python33(self) -> None: results = list(tags.cpython_tags((3, 3), abis=["cp33"], platforms=["plat"])) assert results == [ tags.Tag("cp33", "cp33", "plat"), @@ -1036,7 +1038,7 @@ def test_abi3_python33(self): tags.Tag("cp32", "abi3", "plat"), ] - def test_no_excess_abi3_python32(self): + def test_no_excess_abi3_python32(self) -> None: results = list(tags.cpython_tags((3, 2), abis=["cp32"], platforms=["plat"])) assert results == [ tags.Tag("cp32", "cp32", "plat"), @@ -1044,14 +1046,14 @@ def test_no_excess_abi3_python32(self): tags.Tag("cp32", "none", "plat"), ] - def test_no_abi3_python31(self): + def test_no_abi3_python31(self) -> None: results = list(tags.cpython_tags((3, 1), abis=["cp31"], platforms=["plat"])) assert results == [ tags.Tag("cp31", "cp31", "plat"), tags.Tag("cp31", "none", "plat"), ] - def test_no_abi3_python27(self): + def test_no_abi3_python27(self) -> None: results = list(tags.cpython_tags((2, 7), abis=["cp27"], platforms=["plat"])) assert results == [ tags.Tag("cp27", "cp27", "plat"), @@ -1060,14 +1062,14 @@ def test_no_abi3_python27(self): class TestGenericTags: - def test__generic_abi_macos(self, monkeypatch): + def test__generic_abi_macos(self, monkeypatch) -> None: monkeypatch.setattr( sysconfig, "get_config_var", lambda _: ".cpython-37m-darwin.so" ) monkeypatch.setattr(tags, "interpreter_name", lambda: "cp") assert tags._generic_abi() == ["cp37m"] - def test__generic_abi_linux_cpython(self, monkeypatch): + def test__generic_abi_linux_cpython(self, monkeypatch) -> None: config = { "Py_DEBUG": False, "WITH_PYMALLOC": True, @@ -1079,17 +1081,17 @@ def test__generic_abi_linux_cpython(self, monkeypatch): assert tags._cpython_abis((3, 7)) == ["cp37m"] assert tags._generic_abi() == ["cp37m"] - def test__generic_abi_jp(self, monkeypatch): + def test__generic_abi_jp(self, monkeypatch) -> None: config = {"EXT_SUFFIX": ".return_exactly_this.so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == ["return_exactly_this"] - def test__generic_abi_graal(self, monkeypatch): + def test__generic_abi_graal(self, monkeypatch) -> None: config = {"EXT_SUFFIX": ".graalpy-38-native-x86_64-darwin.so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == ["graalpy_38_native"] - def test__generic_abi_disable_gil(self, monkeypatch): + def test__generic_abi_disable_gil(self, monkeypatch) -> None: config = { "Py_DEBUG": False, "EXT_SUFFIX": ".cpython-313t-x86_64-linux-gnu.so", @@ -1100,20 +1102,20 @@ def test__generic_abi_disable_gil(self, monkeypatch): assert tags._generic_abi() == ["cp313t"] assert tags._generic_abi() == tags._cpython_abis((3, 13)) - def test__generic_abi_none(self, monkeypatch): + def test__generic_abi_none(self, monkeypatch) -> None: config = {"EXT_SUFFIX": "..so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == [] @pytest.mark.parametrize("ext_suffix", ["invalid", None]) - def test__generic_abi_error(self, ext_suffix, monkeypatch): + def test__generic_abi_error(self, ext_suffix, monkeypatch) -> None: config = {"EXT_SUFFIX": ext_suffix} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) with pytest.raises(SystemError) as e: tags._generic_abi() assert "EXT_SUFFIX" in str(e.value) - def test__generic_abi_linux_pypy(self, monkeypatch): + def test__generic_abi_linux_pypy(self, monkeypatch) -> None: # issue gh-606 config = { "Py_DEBUG": False, @@ -1123,7 +1125,7 @@ def test__generic_abi_linux_pypy(self, monkeypatch): monkeypatch.setattr(tags, "interpreter_name", lambda: "pp") assert tags._generic_abi() == ["pypy39_pp73"] - def test__generic_abi_old_windows(self, monkeypatch): + def test__generic_abi_old_windows(self, monkeypatch) -> None: config = { "EXT_SUFFIX": ".pyd", "Py_DEBUG": 0, @@ -1133,7 +1135,7 @@ def test__generic_abi_old_windows(self, monkeypatch): monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == tags._cpython_abis(sys.version_info[:2]) - def test__generic_abi_windows(self, monkeypatch): + def test__generic_abi_windows(self, monkeypatch) -> None: config = { "EXT_SUFFIX": ".cp310-win_amd64.pyd", } @@ -1141,26 +1143,26 @@ def test__generic_abi_windows(self, monkeypatch): assert tags._generic_abi() == ["cp310"] @pytest.mark.skipif(sys.implementation.name != "cpython", reason="CPython-only") - def test__generic_abi_agree(self): + def test__generic_abi_agree(self) -> None: """Test that the two methods of finding the abi tag agree""" assert tags._generic_abi() == tags._cpython_abis(sys.version_info[:2]) - def test_generic_platforms(self): + def test_generic_platforms(self) -> None: platform = sysconfig.get_platform().replace("-", "_") platform = platform.replace(".", "_") assert list(tags._generic_platforms()) == [platform] - def test_generic_platforms_space(self, monkeypatch): + def test_generic_platforms_space(self, monkeypatch) -> None: """Ensure platform tags normalize spaces to underscores.""" platform_ = "isilon onefs" monkeypatch.setattr(sysconfig, "get_platform", lambda: platform_) assert list(tags._generic_platforms()) == [platform_.replace(" ", "_")] - def test_iterator_returned(self): + def test_iterator_returned(self) -> None: result_iterator = tags.generic_tags("sillywalk33", ["abi"], ["plat1", "plat2"]) assert isinstance(result_iterator, collections.abc.Iterator) - def test_all_args(self): + def test_all_args(self) -> None: result_iterator = tags.generic_tags("sillywalk33", ["abi"], ["plat1", "plat2"]) result = list(result_iterator) assert result == [ @@ -1171,20 +1173,20 @@ def test_all_args(self): ] @pytest.mark.parametrize("abi", [[], ["none"]]) - def test_abi_unspecified(self, abi): + def test_abi_unspecified(self, abi) -> None: no_abi = list(tags.generic_tags("sillywalk34", abi, ["plat1", "plat2"])) assert no_abi == [ tags.Tag("sillywalk34", "none", "plat1"), tags.Tag("sillywalk34", "none", "plat2"), ] - def test_interpreter_default(self, monkeypatch): + def test_interpreter_default(self, monkeypatch) -> None: monkeypatch.setattr(tags, "interpreter_name", lambda: "sillywalk") monkeypatch.setattr(tags, "interpreter_version", lambda warn: "NN") # noqa: ARG005 result = list(tags.generic_tags(abis=["none"], platforms=["any"])) assert result == [tags.Tag("sillywalkNN", "none", "any")] - def test_abis_default(self, monkeypatch): + def test_abis_default(self, monkeypatch) -> None: monkeypatch.setattr(tags, "_generic_abi", lambda: ["abi"]) result = list(tags.generic_tags(interpreter="sillywalk", platforms=["any"])) assert result == [ @@ -1192,14 +1194,14 @@ def test_abis_default(self, monkeypatch): tags.Tag("sillywalk", "none", "any"), ] - def test_platforms_default(self, monkeypatch): + def test_platforms_default(self, monkeypatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat"]) result = list(tags.generic_tags(interpreter="sillywalk", abis=["none"])) assert result == [tags.Tag("sillywalk", "none", "plat")] class TestCompatibleTags: - def test_all_args(self): + def test_all_args(self) -> None: result = list(tags.compatible_tags((3, 3), "cp33", ["plat1", "plat2"])) assert result == [ tags.Tag("py33", "none", "plat1"), @@ -1220,7 +1222,7 @@ def test_all_args(self): tags.Tag("py30", "none", "any"), ] - def test_all_args_needs_underscore(self): + def test_all_args_needs_underscore(self) -> None: result = list(tags.compatible_tags((3, 11), "cp311", ["plat1", "plat2"])) assert result == [ tags.Tag("py311", "none", "plat1"), @@ -1265,7 +1267,7 @@ def test_all_args_needs_underscore(self): tags.Tag("py30", "none", "any"), ] - def test_major_only_python_version(self): + def test_major_only_python_version(self) -> None: result = list(tags.compatible_tags((3,), "cp33", ["plat"])) assert result == [ tags.Tag("py3", "none", "plat"), @@ -1273,7 +1275,7 @@ def test_major_only_python_version(self): tags.Tag("py3", "none", "any"), ] - def test_default_python_version(self, monkeypatch): + def test_default_python_version(self, monkeypatch) -> None: monkeypatch.setattr(sys, "version_info", (3, 1)) result = list(tags.compatible_tags(interpreter="cp31", platforms=["plat"])) assert result == [ @@ -1286,7 +1288,7 @@ def test_default_python_version(self, monkeypatch): tags.Tag("py30", "none", "any"), ] - def test_default_python_version_needs_underscore(self, monkeypatch): + def test_default_python_version_needs_underscore(self, monkeypatch) -> None: monkeypatch.setattr(sys, "version_info", (3, 11)) result = list(tags.compatible_tags(interpreter="cp311", platforms=["plat"])) assert result == [ @@ -1319,7 +1321,7 @@ def test_default_python_version_needs_underscore(self, monkeypatch): tags.Tag("py30", "none", "any"), ] - def test_default_interpreter(self): + def test_default_interpreter(self) -> None: result = list(tags.compatible_tags((3, 1), platforms=["plat"])) assert result == [ tags.Tag("py31", "none", "plat"), @@ -1330,7 +1332,7 @@ def test_default_interpreter(self): tags.Tag("py30", "none", "any"), ] - def test_default_platforms(self, monkeypatch): + def test_default_platforms(self, monkeypatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: iter(["plat", "plat2"])) result = list(tags.compatible_tags((3, 1), "cp31")) assert result == [ @@ -1356,14 +1358,14 @@ def teardown_method(self): ("name", "expected"), [("CPython", "cp"), ("PyPy", "pp"), ("Jython", "jy"), ("IronPython", "ip")], ) - def test_interpreter_name(self, name, expected, mock_interpreter_name): + def test_interpreter_name(self, name, expected, mock_interpreter_name) -> None: mock_interpreter_name(name) assert tags.interpreter_name() == expected - def test_iterator(self): + def test_iterator(self) -> None: assert isinstance(tags.sys_tags(), collections.abc.Iterator) - def test_mac_cpython(self, mock_interpreter_name, monkeypatch): + def test_mac_cpython(self, mock_interpreter_name, monkeypatch) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Darwin": @@ -1380,7 +1382,7 @@ def test_mac_cpython(self, mock_interpreter_name, monkeypatch): "py" + tags._version_nodot((sys.version_info[0], 0)), "none", "any" ) - def test_windows_cpython(self, mock_interpreter_name, monkeypatch): + def test_windows_cpython(self, mock_interpreter_name, monkeypatch) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Windows": @@ -1398,7 +1400,7 @@ def test_windows_cpython(self, mock_interpreter_name, monkeypatch): ) assert result[-1] == expected - def test_linux_cpython(self, mock_interpreter_name, monkeypatch): + def test_linux_cpython(self, mock_interpreter_name, monkeypatch) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Linux": @@ -1415,7 +1417,7 @@ def test_linux_cpython(self, mock_interpreter_name, monkeypatch): ) assert result[-1] == expected - def test_generic(self, monkeypatch): + def test_generic(self, monkeypatch) -> None: monkeypatch.setattr(platform, "system", lambda: "Generic") monkeypatch.setattr(tags, "interpreter_name", lambda: "generic") @@ -1426,14 +1428,14 @@ def test_generic(self, monkeypatch): assert result[-1] == expected @pytest.mark.usefixtures("manylinux_module") - def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch): + def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_armv6l") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) platforms = list(tags._linux_platforms(is_32bit=True)) expected = ["linux_armv6l"] assert platforms == expected - def test_skip_manylinux_2014(self, monkeypatch, manylinux_module): + def test_skip_manylinux_2014(self, monkeypatch, manylinux_module) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_ppc64") monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 20)) monkeypatch.setattr( @@ -1501,7 +1503,9 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): expected.append(f"linux_{machine}") assert platforms == expected - def test_linux_use_manylinux_compatible_none(self, monkeypatch, manylinux_module): + def test_linux_use_manylinux_compatible_none( + self, monkeypatch, manylinux_module + ) -> None: def manylinux_compatible(tag_major, tag_minor, tag_arch): # noqa: ARG001 if tag_major == 2 and tag_minor < 25: return False @@ -1527,7 +1531,7 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): # noqa: ARG001 ] assert platforms == expected - def test_pypy_first_none_any_tag(self, monkeypatch): + def test_pypy_first_none_any_tag(self, monkeypatch) -> None: # When building the complete list of pypy tags, make sure the first # -none-any one is pp3-none-any monkeypatch.setattr(tags, "interpreter_name", lambda: "pp") @@ -1538,7 +1542,7 @@ def test_pypy_first_none_any_tag(self, monkeypatch): assert tag == tags.Tag("pp3", "none", "any") - def test_cpython_first_none_any_tag(self, monkeypatch): + def test_cpython_first_none_any_tag(self, monkeypatch) -> None: # When building the complete list of cpython tags, make sure the first # -none-any one is cpxx-none-any monkeypatch.setattr(tags, "interpreter_name", lambda: "cp") @@ -1567,7 +1571,9 @@ def teardown_method(self): (2147483647, 8, False), ], ) - def test_32bit_interpreter(self, maxsize, sizeof_voidp, expected, monkeypatch): + def test_32bit_interpreter( + self, maxsize, sizeof_voidp, expected, monkeypatch + ) -> None: def _calcsize(fmt): assert fmt == "P" return sizeof_voidp @@ -1578,7 +1584,7 @@ def _calcsize(fmt): assert expected == tags._32_BIT_INTERPRETER -def test_pickle(): +def test_pickle() -> None: # Make sure equality works between a pickle/unpickle round trip. tag = tags.Tag("py3", "none", "any") assert pickle.loads(pickle.dumps(tag)) == tag diff --git a/tests/test_utils.py b/tests/test_utils.py index d19776a5b..d18c6e7c2 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -33,7 +33,7 @@ ("foo----bar", "foo-bar"), ], ) -def test_canonicalize_name(name, expected): +def test_canonicalize_name(name, expected) -> None: assert canonicalize_name(name) == expected @@ -49,7 +49,7 @@ def test_canonicalize_name(name, expected): ("h\ri", "h\ri"), ], ) -def test_canonicalize_name_invalid(name, expected): +def test_canonicalize_name_invalid(name, expected) -> None: with pytest.raises(InvalidName): canonicalize_name(name, validate=True) assert canonicalize_name(name) == expected @@ -70,7 +70,7 @@ def test_canonicalize_name_invalid(name, expected): ("foo----bar", "foo-bar"), ], ) -def test_is_normalized_name(name, expected): +def test_is_normalized_name(name, expected) -> None: assert is_normalized_name(expected) if name != expected: assert not is_normalized_name(name) @@ -95,12 +95,12 @@ def test_is_normalized_name(name, expected): ("1.0.1-test7", "1.0.1-test7"), ], ) -def test_canonicalize_version(version, expected): +def test_canonicalize_version(version, expected) -> None: assert canonicalize_version(version) == expected @pytest.mark.parametrize(("version"), ["1.4.0", "1.0"]) -def test_canonicalize_version_no_strip_trailing_zero(version): +def test_canonicalize_version_no_strip_trailing_zero(version) -> None: assert canonicalize_version(version, strip_trailing_zero=False) == version @@ -151,7 +151,7 @@ def test_canonicalize_version_no_strip_trailing_zero(version): ), ], ) -def test_parse_wheel_filename(filename, name, version, build, tags): +def test_parse_wheel_filename(filename, name, version, build, tags) -> None: assert parse_wheel_filename(filename) == (name, version, build, tags) @@ -168,7 +168,7 @@ def test_parse_wheel_filename(filename, name, version, build, tags): ("foo-1.0-200-py3-none-any-junk.whl"), # Too many dashes (`-junk`) ], ) -def test_parse_wheel_invalid_filename(filename): +def test_parse_wheel_invalid_filename(filename) -> None: with pytest.raises(InvalidWheelFilename): parse_wheel_filename(filename) @@ -177,7 +177,7 @@ def test_parse_wheel_invalid_filename(filename): ("filename", "name", "version"), [("foo-1.0.tar.gz", "foo", Version("1.0")), ("foo-1.0.zip", "foo", Version("1.0"))], ) -def test_parse_sdist_filename(filename, name, version): +def test_parse_sdist_filename(filename, name, version) -> None: assert parse_sdist_filename(filename) == (name, version) @@ -189,6 +189,6 @@ def test_parse_sdist_filename(filename, name, version): ("foo-1.x.tar.gz"), # Invalid version ], ) -def test_parse_sdist_invalid_filename(filename): +def test_parse_sdist_invalid_filename(filename) -> None: with pytest.raises(InvalidSdistFilename): parse_sdist_filename(filename) diff --git a/tests/test_version.py b/tests/test_version.py index 42e1934e0..8c672866b 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -11,11 +11,11 @@ from packaging.version import InvalidVersion, Version, parse -def test_parse(): +def test_parse() -> None: assert isinstance(parse("1.0"), Version) -def test_parse_raises(): +def test_parse_raises() -> None: with pytest.raises(InvalidVersion): parse("lolwat") @@ -83,7 +83,7 @@ def test_parse_raises(): class TestVersion: @pytest.mark.parametrize("version", VERSIONS) - def test_valid_versions(self, version): + def test_valid_versions(self, version: str) -> None: Version(version) @pytest.mark.parametrize( @@ -99,7 +99,7 @@ def test_valid_versions(self, version): "1.0+1+1", ], ) - def test_invalid_versions(self, version): + def test_invalid_versions(self, version: str) -> None: with pytest.raises(InvalidVersion): Version(version) @@ -217,7 +217,7 @@ def test_invalid_versions(self, version): (" v1.0\t\n", "1.0"), ], ) - def test_normalized_versions(self, version, normalized): + def test_normalized_versions(self, version: str, normalized: str) -> None: assert str(Version(version)) == normalized @pytest.mark.parametrize( @@ -272,15 +272,15 @@ def test_normalized_versions(self, version, normalized): ("7!1.1.dev1", "7!1.1.dev1"), ], ) - def test_version_str_repr(self, version, expected): + def test_version_str_repr(self, version: str, expected: str) -> None: assert str(Version(version)) == expected assert repr(Version(version)) == f"" - def test_version_rc_and_c_equals(self): + def test_version_rc_and_c_equals(self) -> None: assert Version("1.0rc1") == Version("1.0c1") @pytest.mark.parametrize("version", VERSIONS) - def test_version_hash(self, version): + def test_version_hash(self, version: str) -> None: assert hash(Version(version)) == hash(Version(version)) @pytest.mark.parametrize( @@ -317,7 +317,7 @@ def test_version_hash(self, version): ("1!1.0.post5+deadbeef", "1!1.0.post5"), ], ) - def test_version_public(self, version, public): + def test_version_public(self, version, public) -> None: assert Version(version).public == public @pytest.mark.parametrize( @@ -354,7 +354,7 @@ def test_version_public(self, version, public): ("1!1.0.post5+deadbeef", "1!1.0"), ], ) - def test_version_base_version(self, version, base_version): + def test_version_base_version(self, version, base_version) -> None: assert Version(version).base_version == base_version @pytest.mark.parametrize( @@ -391,7 +391,7 @@ def test_version_base_version(self, version, base_version): ("1!1.0.post5+deadbeef", 1), ], ) - def test_version_epoch(self, version, epoch): + def test_version_epoch(self, version, epoch) -> None: assert Version(version).epoch == epoch @pytest.mark.parametrize( @@ -428,7 +428,7 @@ def test_version_epoch(self, version, epoch): ("1!1.0.post5+deadbeef", (1, 0)), ], ) - def test_version_release(self, version, release): + def test_version_release(self, version, release) -> None: assert Version(version).release == release @pytest.mark.parametrize( @@ -465,7 +465,7 @@ def test_version_release(self, version, release): ("1!1.0.post5+deadbeef", "deadbeef"), ], ) - def test_version_local(self, version, local): + def test_version_local(self, version, local) -> None: assert Version(version).local == local @pytest.mark.parametrize( @@ -502,7 +502,7 @@ def test_version_local(self, version, local): ("1!1.0.post5+deadbeef", None), ], ) - def test_version_pre(self, version, pre): + def test_version_pre(self, version, pre) -> None: assert Version(version).pre == pre @pytest.mark.parametrize( @@ -532,7 +532,7 @@ def test_version_pre(self, version, pre): ("1.0.post1+dev", False), ], ) - def test_version_is_prerelease(self, version, expected): + def test_version_is_prerelease(self, version, expected) -> None: assert Version(version).is_prerelease is expected @pytest.mark.parametrize( @@ -569,7 +569,7 @@ def test_version_is_prerelease(self, version, expected): ("1!1.0.post5+deadbeef", None), ], ) - def test_version_dev(self, version, dev): + def test_version_dev(self, version, dev) -> None: assert Version(version).dev == dev @pytest.mark.parametrize( @@ -606,7 +606,7 @@ def test_version_dev(self, version, dev): ("1!1.0.post5+deadbeef", False), ], ) - def test_version_is_devrelease(self, version, expected): + def test_version_is_devrelease(self, version, expected) -> None: assert Version(version).is_devrelease is expected @pytest.mark.parametrize( @@ -643,7 +643,7 @@ def test_version_is_devrelease(self, version, expected): ("1!1.0.post5+deadbeef", 5), ], ) - def test_version_post(self, version, post): + def test_version_post(self, version, post) -> None: assert Version(version).post == post @pytest.mark.parametrize( @@ -656,7 +656,7 @@ def test_version_post(self, version, post): ("1.0.post1", True), ], ) - def test_version_is_postrelease(self, version, expected): + def test_version_is_postrelease(self, version, expected) -> None: assert Version(version).is_postrelease is expected @pytest.mark.parametrize( @@ -698,7 +698,7 @@ def test_version_is_postrelease(self, version, expected): ] ), ) - def test_comparison_true(self, left, right, op): + def test_comparison_true(self, left, right, op) -> None: assert op(Version(left), Version(right)) @pytest.mark.parametrize( @@ -740,28 +740,28 @@ def test_comparison_true(self, left, right, op): ] ), ) - def test_comparison_false(self, left, right, op): + def test_comparison_false(self, left, right, op) -> None: assert not op(Version(left), Version(right)) @pytest.mark.parametrize("op", ["lt", "le", "eq", "ge", "gt", "ne"]) - def test_dunder_op_returns_notimplemented(self, op): + def test_dunder_op_returns_notimplemented(self, op) -> None: method = getattr(Version, f"__{op}__") assert method(Version("1"), 1) is NotImplemented @pytest.mark.parametrize(("op", "expected"), [("eq", False), ("ne", True)]) - def test_compare_other(self, op, expected): + def test_compare_other(self, op, expected) -> None: other = pretend.stub(**{f"__{op}__": lambda _: NotImplemented}) assert getattr(operator, op)(Version("1"), other) is expected - def test_major_version(self): + def test_major_version(self) -> None: assert Version("2.1.0").major == 2 - def test_minor_version(self): + def test_minor_version(self) -> None: assert Version("2.1.0").minor == 1 assert Version("2").minor == 0 - def test_micro_version(self): + def test_micro_version(self) -> None: assert Version("2.1.3").micro == 3 assert Version("2.1").micro == 0 assert Version("2").micro == 0 From f0384989eb0a7d99bc8872bf578c53454766d5c3 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 17 Nov 2025 18:14:22 -0500 Subject: [PATCH 2/3] chore: add some fixture types Signed-off-by: Henry Schreiner --- tests/test_manylinux.py | 32 ++++--- tests/test_markers.py | 2 +- tests/test_musllinux.py | 4 +- tests/test_tags.py | 189 ++++++++++++++++++++++++++-------------- 4 files changed, 145 insertions(+), 82 deletions(-) diff --git a/tests/test_manylinux.py b/tests/test_manylinux.py index 83b40e033..ffe7f39a2 100644 --- a/tests/test_manylinux.py +++ b/tests/test_manylinux.py @@ -31,7 +31,7 @@ def clear_lru_cache(): @pytest.fixture -def manylinux_module(monkeypatch): +def manylinux_module(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(_manylinux, "_get_glibc_version", lambda *args: (2, 20)) module_name = "_manylinux" module = types.ModuleType(module_name) @@ -44,7 +44,7 @@ def manylinux_module(monkeypatch): ("attribute", "glibc"), [("1", (2, 5)), ("2010", (2, 12)), ("2014", (2, 17))] ) def test_module_declaration( - monkeypatch, manylinux_module, attribute, glibc, tf + monkeypatch: pytest.MonkeyPatch, manylinux_module, attribute, glibc, tf ) -> None: manylinux = f"manylinux{attribute}_compatible" monkeypatch.setattr(manylinux_module, manylinux, tf, raising=False) @@ -56,7 +56,7 @@ def test_module_declaration( ("attribute", "glibc"), [("1", (2, 5)), ("2010", (2, 12)), ("2014", (2, 17))] ) def test_module_declaration_missing_attribute( - monkeypatch, manylinux_module, attribute, glibc + monkeypatch: pytest.MonkeyPatch, manylinux_module, attribute, glibc ): manylinux = f"manylinux{attribute}_compatible" monkeypatch.delattr(manylinux_module, manylinux, raising=False) @@ -67,7 +67,7 @@ def test_module_declaration_missing_attribute( ("version", "compatible"), [((2, 0), True), ((2, 5), True), ((2, 10), False)] ) def test_is_manylinux_compatible_glibc_support( - version, compatible, monkeypatch + version, compatible, monkeypatch: pytest.MonkeyPatch ) -> None: monkeypatch.setitem(sys.modules, "_manylinux", None) monkeypatch.setattr(_manylinux, "_get_glibc_version", lambda: (2, 5)) @@ -90,7 +90,9 @@ def test_check_glibc_version_warning(version_str) -> None: ("2.4", "2.4"), ], ) -def test_glibc_version_string(version_str, expected, monkeypatch) -> None: +def test_glibc_version_string( + version_str, expected, monkeypatch: pytest.MonkeyPatch +) -> None: class LibcVersion: def __init__(self, version_str): self.version_str = version_str @@ -112,12 +114,12 @@ def __init__(self, libc_version): assert _glibc_version_string() is None -def test_glibc_version_string_confstr(monkeypatch) -> None: +def test_glibc_version_string_confstr(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) assert _glibc_version_string_confstr() == "2.20" -def test_glibc_version_string_fail(monkeypatch) -> None: +def test_glibc_version_string_fail(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(os, "confstr", lambda _: None, raising=False) monkeypatch.setitem(sys.modules, "ctypes", None) assert _glibc_version_string() is None @@ -128,23 +130,27 @@ def test_glibc_version_string_fail(monkeypatch) -> None: "failure", [pretend.raiser(ValueError), pretend.raiser(OSError), lambda _: "XXX"], ) -def test_glibc_version_string_confstr_fail(monkeypatch, failure) -> None: +def test_glibc_version_string_confstr_fail( + monkeypatch: pytest.MonkeyPatch, failure +) -> None: monkeypatch.setattr(os, "confstr", failure, raising=False) assert _glibc_version_string_confstr() is None -def test_glibc_version_string_confstr_missing(monkeypatch) -> None: +def test_glibc_version_string_confstr_missing(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.delattr(os, "confstr", raising=False) assert _glibc_version_string_confstr() is None -def test_glibc_version_string_ctypes_missing(monkeypatch) -> None: +def test_glibc_version_string_ctypes_missing(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setitem(sys.modules, "ctypes", None) assert _glibc_version_string_ctypes() is None @pytest.mark.xfail(ctypes is None, reason="ctypes not available") -def test_glibc_version_string_ctypes_raise_oserror(monkeypatch) -> None: +def test_glibc_version_string_ctypes_raise_oserror( + monkeypatch: pytest.MonkeyPatch, +) -> None: def patched_cdll(_name): raise OSError("Dynamic loading not supported") @@ -159,12 +165,12 @@ def test_is_manylinux_compatible_old() -> None: assert _is_compatible("any", (2, 0)) -def test_is_manylinux_compatible(monkeypatch) -> None: +def test_is_manylinux_compatible(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: "2.4") assert _is_compatible("any", (2, 4)) -def test_glibc_version_string_none(monkeypatch) -> None: +def test_glibc_version_string_none(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: None) assert not _is_compatible("any", (2, 4)) diff --git a/tests/test_markers.py b/tests/test_markers.py index 7b246223b..fa86921f3 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -127,7 +127,7 @@ def test_matches_expected(self) -> None: "sys_platform": sys.platform, } - def test_multidigit_minor_version(self, monkeypatch) -> None: + def test_multidigit_minor_version(self, monkeypatch: pytest.MonkeyPatch) -> None: version_info = (3, 10, 0, "final", 0) monkeypatch.setattr(sys, "version_info", version_info, raising=False) diff --git a/tests/test_musllinux.py b/tests/test_musllinux.py index 5615faefa..593b749e0 100644 --- a/tests/test_musllinux.py +++ b/tests/test_musllinux.py @@ -58,7 +58,9 @@ def test_parse_musl_version(output, version) -> None: ], ids=["does-not-exist", "glibc", "x86_64", "i386", "aarch64"], ) -def test_get_musl_version(monkeypatch, executable, output, version, ld_musl) -> None: +def test_get_musl_version( + monkeypatch: pytest.MonkeyPatch, executable, output, version, ld_musl +) -> None: def mock_run(*args, **kwargs): return collections.namedtuple("Proc", "stderr")(output) diff --git a/tests/test_tags.py b/tests/test_tags.py index 74a14af8d..83a479dd0 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -34,7 +34,7 @@ def example_tag(): @pytest.fixture -def manylinux_module(monkeypatch): +def manylinux_module(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda *args: (2, 20)) module_name = "_manylinux" module = types.ModuleType(module_name) @@ -43,7 +43,7 @@ def manylinux_module(monkeypatch): @pytest.fixture -def mock_interpreter_name(monkeypatch): +def mock_interpreter_name(monkeypatch: pytest.MonkeyPatch): def mock(name): name = name.lower() if sys.implementation.name != name: @@ -55,7 +55,7 @@ def mock(name): @pytest.fixture -def mock_ios(monkeypatch): +def mock_ios(monkeypatch: pytest.MonkeyPatch): # Monkeypatch the platform to be iOS monkeypatch.setattr(sys, "platform", "ios") @@ -79,7 +79,7 @@ def mock_ios_ver(*args): @pytest.fixture -def mock_android(monkeypatch): +def mock_android(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(sys, "platform", "android") monkeypatch.setattr(platform, "system", lambda: "Android") monkeypatch.setattr(sysconfig, "get_platform", lambda: "android-21-arm64_v8a") @@ -159,7 +159,7 @@ def test_multi_platform(self) -> None: class TestInterpreterName: - def test_sys_implementation_name(self, monkeypatch) -> None: + def test_sys_implementation_name(self, monkeypatch: pytest.MonkeyPatch) -> None: class MockImplementation: pass @@ -174,7 +174,7 @@ def test_interpreter_short_names(self, mock_interpreter_name) -> None: class TestInterpreterVersion: - def test_warn(self, monkeypatch) -> None: + def test_warn(self, monkeypatch: pytest.MonkeyPatch) -> None: class MockConfigVar: def __init__(self, return_): self.warn = None @@ -189,7 +189,7 @@ def __call__(self, _name, warn): tags.interpreter_version(warn=True) assert mock_config_var.warn - def test_python_version_nodot(self, monkeypatch) -> None: + def test_python_version_nodot(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "_get_config_var", lambda _var, warn: "NN") # noqa: ARG005 assert tags.interpreter_version() == "NN" @@ -203,7 +203,9 @@ def test_python_version_nodot(self, monkeypatch) -> None: ((1, 2, 13), "12"), ], ) - def test_sys_version_info(self, version_info, version_str, monkeypatch) -> None: + def test_sys_version_info( + self, version_info, version_str, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(tags, "_get_config_var", lambda *args, **kwargs: None) monkeypatch.setattr(sys, "version_info", version_info) assert tags.interpreter_version() == version_str @@ -266,7 +268,7 @@ def test_architectures(self, arch, is_32bit, expected) -> None: def test_binary_formats(self, version, arch, expected) -> None: assert tags._mac_binary_formats(version, arch) == expected - def test_version_detection(self, monkeypatch) -> None: + def test_version_detection(self, monkeypatch: pytest.MonkeyPatch) -> None: if platform.system() != "Darwin": monkeypatch.setattr( platform, "mac_ver", lambda: ("10.14", ("", "", ""), "x86_64") @@ -286,7 +288,7 @@ def test_version_detection(self, monkeypatch) -> None: expected = f"macosx_{major}_{minor}_" assert platforms[0].startswith(expected) - def test_version_detection_10_15(self, monkeypatch) -> None: + def test_version_detection_10_15(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( platform, "mac_ver", lambda: ("10.15", ("", "", ""), "x86_64") ) @@ -295,7 +297,9 @@ def test_version_detection_10_15(self, monkeypatch) -> None: platforms = list(tags.mac_platforms(arch="x86_64")) assert platforms[0].startswith(expected) - def test_version_detection_compatibility(self, monkeypatch) -> None: + def test_version_detection_compatibility( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: if platform.system() != "Darwin": monkeypatch.setattr( subprocess, @@ -313,7 +317,7 @@ def test_version_detection_compatibility(self, monkeypatch) -> None: assert not platforms[0].startswith(unexpected) @pytest.mark.parametrize("arch", ["x86_64", "i386"]) - def test_arch_detection(self, arch, monkeypatch) -> None: + def test_arch_detection(self, arch, monkeypatch: pytest.MonkeyPatch) -> None: if platform.system() != "Darwin" or platform.mac_ver()[2] != arch: monkeypatch.setattr( platform, "mac_ver", lambda: ("10.14", ("", "", ""), arch) @@ -527,13 +531,13 @@ def teardown_method(self): # Clear the version cache tags._manylinux._get_glibc_version.cache_clear() - def test_get_config_var_does_not_log(self, monkeypatch) -> None: + def test_get_config_var_does_not_log(self, monkeypatch: pytest.MonkeyPatch) -> None: debug = pretend.call_recorder(lambda *a: None) monkeypatch.setattr(tags.logger, "debug", debug) tags._get_config_var("missing") assert debug.calls == [] - def test_get_config_var_does_log(self, monkeypatch) -> None: + def test_get_config_var_does_log(self, monkeypatch: pytest.MonkeyPatch) -> None: debug = pretend.call_recorder(lambda *a: None) monkeypatch.setattr(tags.logger, "debug", debug) tags._get_config_var("missing", warn=True) @@ -554,7 +558,7 @@ def test_get_config_var_does_log(self, monkeypatch) -> None: ], ) def test_linux_platforms_32_64bit_on_64bit_os( - self, arch, is_32bit, expected, monkeypatch + self, arch, is_32bit, expected, monkeypatch: pytest.MonkeyPatch ): monkeypatch.setattr(sysconfig, "get_platform", lambda: arch) monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) @@ -564,14 +568,16 @@ def test_linux_platforms_32_64bit_on_64bit_os( ] assert linux_platform == expected - def test_linux_platforms_manylinux_unsupported(self, monkeypatch) -> None: + def test_linux_platforms_manylinux_unsupported( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) linux_platform = list(tags._linux_platforms(is_32bit=False)) assert linux_platform == ["linux_x86_64"] - def test_linux_platforms_manylinux1(self, monkeypatch) -> None: + def test_linux_platforms_manylinux1(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( tags._manylinux, "_is_compatible", @@ -587,7 +593,9 @@ def test_linux_platforms_manylinux1(self, monkeypatch) -> None: "linux_x86_64", ] - def test_linux_platforms_manylinux2010(self, monkeypatch) -> None: + def test_linux_platforms_manylinux2010( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.12", raising=False) @@ -607,7 +615,9 @@ def test_linux_platforms_manylinux2010(self, monkeypatch) -> None: ] assert platforms == expected - def test_linux_platforms_manylinux2014(self, monkeypatch) -> None: + def test_linux_platforms_manylinux2014( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.17", raising=False) @@ -639,7 +649,7 @@ def test_linux_platforms_manylinux2014(self, monkeypatch) -> None: [("armv7l", "armv7l"), ("armv8l", "armv8l"), ("aarch64", "armv8l")], ) def test_linux_platforms_manylinux2014_armhf_abi( - self, native_arch, cross_arch, monkeypatch + self, native_arch, cross_arch, monkeypatch: pytest.MonkeyPatch ): monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.30") monkeypatch.setattr( @@ -665,7 +675,9 @@ def test_linux_platforms_manylinux2014_armhf_abi( expected.extend(f"linux_{arch}" for arch in archs) assert platforms == expected - def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch) -> None: + def test_linux_platforms_manylinux2014_i386_abi( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.17") monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr( @@ -699,7 +711,9 @@ def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch) -> None: ] assert platforms == expected - def test_linux_platforms_manylinux_glibc3(self, monkeypatch) -> None: + def test_linux_platforms_manylinux_glibc3( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: # test for a future glic 3.x version monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "3.2") monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: True) @@ -732,7 +746,12 @@ def test_linux_platforms_manylinux_glibc3(self, monkeypatch) -> None: ) @pytest.mark.parametrize("cross32", [True, False], ids=["cross", "native"]) def test_linux_platforms_musllinux( - self, monkeypatch, native_arch, cross32_arch, musl_version, cross32 + self, + monkeypatch: pytest.MonkeyPatch, + native_arch, + cross32_arch, + musl_version, + cross32, ): fake_executable = str( pathlib.Path(__file__) @@ -760,7 +779,9 @@ def test_linux_platforms_musllinux( assert recorder.calls == [pretend.call(fake_executable)] - def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch) -> None: + def test_linux_platforms_manylinux2014_armv6l( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr( tags._manylinux, "_is_compatible", @@ -777,7 +798,7 @@ def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch) -> None: [("x86_64", "x32", "i686"), ("armv7l", "armel", "armv7l")], ) def test_linux_platforms_not_manylinux_abi( - self, monkeypatch, machine, abi, alt_machine + self, monkeypatch: pytest.MonkeyPatch, machine, abi, alt_machine ): monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{machine}") @@ -794,7 +815,7 @@ def test_linux_platforms_not_manylinux_abi( expected = [f"linux_{alt_machine}"] assert platforms == expected - def test_linux_not_linux(self, monkeypatch) -> None: + def test_linux_not_linux(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "not_linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.17", raising=False) @@ -812,14 +833,16 @@ def test_linux_not_linux(self, monkeypatch) -> None: ("Generic", "_generic_platforms"), ], ) -def test_platform_tags(platform_name, dispatch_func, monkeypatch) -> None: +def test_platform_tags( + platform_name, dispatch_func, monkeypatch: pytest.MonkeyPatch +) -> None: expected = ["sillywalk"] monkeypatch.setattr(platform, "system", lambda: platform_name) monkeypatch.setattr(tags, dispatch_func, lambda: expected) assert tags.platform_tags() == expected -def test_platform_tags_space(monkeypatch) -> None: +def test_platform_tags_space(monkeypatch: pytest.MonkeyPatch) -> None: """Ensure spaces in platform tags are normalized to underscores.""" monkeypatch.setattr(platform, "system", lambda: "Isilon OneFS") monkeypatch.setattr(sysconfig, "get_platform", lambda: "isilon onefs") @@ -831,7 +854,9 @@ class TestCPythonABI: ("py_debug", "gettotalrefcount", "result"), [(1, False, True), (0, False, False), (None, True, True)], ) - def test_debug(self, py_debug, gettotalrefcount, result, monkeypatch) -> None: + def test_debug( + self, py_debug, gettotalrefcount, result, monkeypatch: pytest.MonkeyPatch + ) -> None: config = {"Py_DEBUG": py_debug, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) if gettotalrefcount: @@ -839,7 +864,7 @@ def test_debug(self, py_debug, gettotalrefcount, result, monkeypatch) -> None: expected = ["cp37d" if result else "cp37"] assert tags._cpython_abis((3, 7)) == expected - def test_debug_file_extension(self, monkeypatch) -> None: + def test_debug_file_extension(self, monkeypatch: pytest.MonkeyPatch) -> None: config = {"Py_DEBUG": None} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) monkeypatch.delattr(sys, "gettotalrefcount", raising=False) @@ -849,7 +874,9 @@ def test_debug_file_extension(self, monkeypatch) -> None: @pytest.mark.parametrize( ("debug", "expected"), [(True, ["cp38d", "cp38"]), (False, ["cp38"])] ) - def test__debug_cp38(self, debug, expected, monkeypatch) -> None: + def test__debug_cp38( + self, debug, expected, monkeypatch: pytest.MonkeyPatch + ) -> None: config = {"Py_DEBUG": debug} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._cpython_abis((3, 8)) == expected @@ -863,7 +890,9 @@ def test__debug_cp38(self, debug, expected, monkeypatch) -> None: (1, (3, 8), False), ], ) - def test_pymalloc(self, pymalloc, version, result, monkeypatch) -> None: + def test_pymalloc( + self, pymalloc, version, result, monkeypatch: pytest.MonkeyPatch + ) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": pymalloc, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) base_abi = f"cp{version[0]}{version[1]}" @@ -881,7 +910,7 @@ def test_pymalloc(self, pymalloc, version, result, monkeypatch) -> None: ], ) def test_wide_unicode( - self, unicode_size, maxunicode, version, result, monkeypatch + self, unicode_size, maxunicode, version, result, monkeypatch: pytest.MonkeyPatch ) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": unicode_size} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -983,31 +1012,37 @@ def test_python_version_defaults(self) -> None: interpreter = "cp" + tags._version_nodot(sys.version_info[:2]) assert interpreter == tag.interpreter - def test_abi_defaults(self, monkeypatch) -> None: + def test_abi_defaults(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "_cpython_abis", lambda _1, _2: ["cp38"]) result = list(tags.cpython_tags((3, 8), platforms=["any"])) assert tags.Tag("cp38", "cp38", "any") in result assert tags.Tag("cp38", "abi3", "any") in result assert tags.Tag("cp38", "none", "any") in result - def test_abi_defaults_needs_underscore(self, monkeypatch) -> None: + def test_abi_defaults_needs_underscore( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(tags, "_cpython_abis", lambda _1, _2: ["cp311"]) result = list(tags.cpython_tags((3, 11), platforms=["any"])) assert tags.Tag("cp311", "cp311", "any") in result assert tags.Tag("cp311", "abi3", "any") in result assert tags.Tag("cp311", "none", "any") in result - def test_platforms_defaults(self, monkeypatch) -> None: + def test_platforms_defaults(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat1"]) result = list(tags.cpython_tags((3, 8), abis=["whatever"])) assert tags.Tag("cp38", "whatever", "plat1") in result - def test_platforms_defaults_needs_underscore(self, monkeypatch) -> None: + def test_platforms_defaults_needs_underscore( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat1"]) result = list(tags.cpython_tags((3, 11), abis=["whatever"])) assert tags.Tag("cp311", "whatever", "plat1") in result - def test_platform_name_space_normalization(self, monkeypatch) -> None: + def test_platform_name_space_normalization( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: """Ensure that spaces are translated to underscores in platform names.""" monkeypatch.setattr(sysconfig, "get_platform", lambda: "isilon onefs") for tag in tags.cpython_tags(): @@ -1062,14 +1097,14 @@ def test_no_abi3_python27(self) -> None: class TestGenericTags: - def test__generic_abi_macos(self, monkeypatch) -> None: + def test__generic_abi_macos(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( sysconfig, "get_config_var", lambda _: ".cpython-37m-darwin.so" ) monkeypatch.setattr(tags, "interpreter_name", lambda: "cp") assert tags._generic_abi() == ["cp37m"] - def test__generic_abi_linux_cpython(self, monkeypatch) -> None: + def test__generic_abi_linux_cpython(self, monkeypatch: pytest.MonkeyPatch) -> None: config = { "Py_DEBUG": False, "WITH_PYMALLOC": True, @@ -1081,17 +1116,17 @@ def test__generic_abi_linux_cpython(self, monkeypatch) -> None: assert tags._cpython_abis((3, 7)) == ["cp37m"] assert tags._generic_abi() == ["cp37m"] - def test__generic_abi_jp(self, monkeypatch) -> None: + def test__generic_abi_jp(self, monkeypatch: pytest.MonkeyPatch) -> None: config = {"EXT_SUFFIX": ".return_exactly_this.so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == ["return_exactly_this"] - def test__generic_abi_graal(self, monkeypatch) -> None: + def test__generic_abi_graal(self, monkeypatch: pytest.MonkeyPatch) -> None: config = {"EXT_SUFFIX": ".graalpy-38-native-x86_64-darwin.so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == ["graalpy_38_native"] - def test__generic_abi_disable_gil(self, monkeypatch) -> None: + def test__generic_abi_disable_gil(self, monkeypatch: pytest.MonkeyPatch) -> None: config = { "Py_DEBUG": False, "EXT_SUFFIX": ".cpython-313t-x86_64-linux-gnu.so", @@ -1102,20 +1137,22 @@ def test__generic_abi_disable_gil(self, monkeypatch) -> None: assert tags._generic_abi() == ["cp313t"] assert tags._generic_abi() == tags._cpython_abis((3, 13)) - def test__generic_abi_none(self, monkeypatch) -> None: + def test__generic_abi_none(self, monkeypatch: pytest.MonkeyPatch) -> None: config = {"EXT_SUFFIX": "..so"} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == [] @pytest.mark.parametrize("ext_suffix", ["invalid", None]) - def test__generic_abi_error(self, ext_suffix, monkeypatch) -> None: + def test__generic_abi_error( + self, ext_suffix, monkeypatch: pytest.MonkeyPatch + ) -> None: config = {"EXT_SUFFIX": ext_suffix} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) with pytest.raises(SystemError) as e: tags._generic_abi() assert "EXT_SUFFIX" in str(e.value) - def test__generic_abi_linux_pypy(self, monkeypatch) -> None: + def test__generic_abi_linux_pypy(self, monkeypatch: pytest.MonkeyPatch) -> None: # issue gh-606 config = { "Py_DEBUG": False, @@ -1125,7 +1162,7 @@ def test__generic_abi_linux_pypy(self, monkeypatch) -> None: monkeypatch.setattr(tags, "interpreter_name", lambda: "pp") assert tags._generic_abi() == ["pypy39_pp73"] - def test__generic_abi_old_windows(self, monkeypatch) -> None: + def test__generic_abi_old_windows(self, monkeypatch: pytest.MonkeyPatch) -> None: config = { "EXT_SUFFIX": ".pyd", "Py_DEBUG": 0, @@ -1135,7 +1172,7 @@ def test__generic_abi_old_windows(self, monkeypatch) -> None: monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) assert tags._generic_abi() == tags._cpython_abis(sys.version_info[:2]) - def test__generic_abi_windows(self, monkeypatch) -> None: + def test__generic_abi_windows(self, monkeypatch: pytest.MonkeyPatch) -> None: config = { "EXT_SUFFIX": ".cp310-win_amd64.pyd", } @@ -1152,7 +1189,7 @@ def test_generic_platforms(self) -> None: platform = platform.replace(".", "_") assert list(tags._generic_platforms()) == [platform] - def test_generic_platforms_space(self, monkeypatch) -> None: + def test_generic_platforms_space(self, monkeypatch: pytest.MonkeyPatch) -> None: """Ensure platform tags normalize spaces to underscores.""" platform_ = "isilon onefs" monkeypatch.setattr(sysconfig, "get_platform", lambda: platform_) @@ -1180,13 +1217,13 @@ def test_abi_unspecified(self, abi) -> None: tags.Tag("sillywalk34", "none", "plat2"), ] - def test_interpreter_default(self, monkeypatch) -> None: + def test_interpreter_default(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "interpreter_name", lambda: "sillywalk") monkeypatch.setattr(tags, "interpreter_version", lambda warn: "NN") # noqa: ARG005 result = list(tags.generic_tags(abis=["none"], platforms=["any"])) assert result == [tags.Tag("sillywalkNN", "none", "any")] - def test_abis_default(self, monkeypatch) -> None: + def test_abis_default(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "_generic_abi", lambda: ["abi"]) result = list(tags.generic_tags(interpreter="sillywalk", platforms=["any"])) assert result == [ @@ -1194,7 +1231,7 @@ def test_abis_default(self, monkeypatch) -> None: tags.Tag("sillywalk", "none", "any"), ] - def test_platforms_default(self, monkeypatch) -> None: + def test_platforms_default(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: ["plat"]) result = list(tags.generic_tags(interpreter="sillywalk", abis=["none"])) assert result == [tags.Tag("sillywalk", "none", "plat")] @@ -1275,7 +1312,7 @@ def test_major_only_python_version(self) -> None: tags.Tag("py3", "none", "any"), ] - def test_default_python_version(self, monkeypatch) -> None: + def test_default_python_version(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(sys, "version_info", (3, 1)) result = list(tags.compatible_tags(interpreter="cp31", platforms=["plat"])) assert result == [ @@ -1288,7 +1325,9 @@ def test_default_python_version(self, monkeypatch) -> None: tags.Tag("py30", "none", "any"), ] - def test_default_python_version_needs_underscore(self, monkeypatch) -> None: + def test_default_python_version_needs_underscore( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(sys, "version_info", (3, 11)) result = list(tags.compatible_tags(interpreter="cp311", platforms=["plat"])) assert result == [ @@ -1332,7 +1371,7 @@ def test_default_interpreter(self) -> None: tags.Tag("py30", "none", "any"), ] - def test_default_platforms(self, monkeypatch) -> None: + def test_default_platforms(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(tags, "platform_tags", lambda: iter(["plat", "plat2"])) result = list(tags.compatible_tags((3, 1), "cp31")) assert result == [ @@ -1365,7 +1404,9 @@ def test_interpreter_name(self, name, expected, mock_interpreter_name) -> None: def test_iterator(self) -> None: assert isinstance(tags.sys_tags(), collections.abc.Iterator) - def test_mac_cpython(self, mock_interpreter_name, monkeypatch) -> None: + def test_mac_cpython( + self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Darwin": @@ -1382,7 +1423,9 @@ def test_mac_cpython(self, mock_interpreter_name, monkeypatch) -> None: "py" + tags._version_nodot((sys.version_info[0], 0)), "none", "any" ) - def test_windows_cpython(self, mock_interpreter_name, monkeypatch) -> None: + def test_windows_cpython( + self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Windows": @@ -1400,7 +1443,9 @@ def test_windows_cpython(self, mock_interpreter_name, monkeypatch) -> None: ) assert result[-1] == expected - def test_linux_cpython(self, mock_interpreter_name, monkeypatch) -> None: + def test_linux_cpython( + self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) if platform.system() != "Linux": @@ -1417,7 +1462,7 @@ def test_linux_cpython(self, mock_interpreter_name, monkeypatch) -> None: ) assert result[-1] == expected - def test_generic(self, monkeypatch) -> None: + def test_generic(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(platform, "system", lambda: "Generic") monkeypatch.setattr(tags, "interpreter_name", lambda: "generic") @@ -1428,14 +1473,18 @@ def test_generic(self, monkeypatch) -> None: assert result[-1] == expected @pytest.mark.usefixtures("manylinux_module") - def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch) -> None: + def test_linux_platforms_manylinux2014_armv6l( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_armv6l") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) platforms = list(tags._linux_platforms(is_32bit=True)) expected = ["linux_armv6l"] assert platforms == expected - def test_skip_manylinux_2014(self, monkeypatch, manylinux_module) -> None: + def test_skip_manylinux_2014( + self, monkeypatch: pytest.MonkeyPatch, manylinux_module + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_ppc64") monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 20)) monkeypatch.setattr( @@ -1458,7 +1507,7 @@ def test_skip_manylinux_2014(self, monkeypatch, manylinux_module) -> None: [("x86_64", "x32", "i686"), ("armv7l", "armel", "armv7l")], ) def test_linux_platforms_not_manylinux_abi( - self, monkeypatch, machine, abi, alt_machine + self, monkeypatch: pytest.MonkeyPatch, machine, abi, alt_machine ): monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{machine}") monkeypatch.setattr( @@ -1479,7 +1528,13 @@ def test_linux_platforms_not_manylinux_abi( [("x86_64", 2, 20, False), ("s390x", 2, 22, True)], ) def test_linux_use_manylinux_compatible( - self, monkeypatch, manylinux_module, machine, major, minor, tf + self, + monkeypatch: pytest.MonkeyPatch, + manylinux_module, + machine, + major, + minor, + tf, ): def manylinux_compatible(tag_major, tag_minor, tag_arch): if tag_major == 2 and tag_minor == 22: @@ -1504,7 +1559,7 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): assert platforms == expected def test_linux_use_manylinux_compatible_none( - self, monkeypatch, manylinux_module + self, monkeypatch: pytest.MonkeyPatch, manylinux_module ) -> None: def manylinux_compatible(tag_major, tag_minor, tag_arch): # noqa: ARG001 if tag_major == 2 and tag_minor < 25: @@ -1531,7 +1586,7 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): # noqa: ARG001 ] assert platforms == expected - def test_pypy_first_none_any_tag(self, monkeypatch) -> None: + def test_pypy_first_none_any_tag(self, monkeypatch: pytest.MonkeyPatch) -> None: # When building the complete list of pypy tags, make sure the first # -none-any one is pp3-none-any monkeypatch.setattr(tags, "interpreter_name", lambda: "pp") @@ -1542,7 +1597,7 @@ def test_pypy_first_none_any_tag(self, monkeypatch) -> None: assert tag == tags.Tag("pp3", "none", "any") - def test_cpython_first_none_any_tag(self, monkeypatch) -> None: + def test_cpython_first_none_any_tag(self, monkeypatch: pytest.MonkeyPatch) -> None: # When building the complete list of cpython tags, make sure the first # -none-any one is cpxx-none-any monkeypatch.setattr(tags, "interpreter_name", lambda: "cp") @@ -1572,7 +1627,7 @@ def teardown_method(self): ], ) def test_32bit_interpreter( - self, maxsize, sizeof_voidp, expected, monkeypatch + self, maxsize, sizeof_voidp, expected, monkeypatch: pytest.MonkeyPatch ) -> None: def _calcsize(fmt): assert fmt == "P" From 9b8686883f1e9cdb2f851f43fb4a58fdd3ed2640 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 17 Nov 2025 21:38:56 -0500 Subject: [PATCH 3/3] chore: work through remaining types Signed-off-by: Henry Schreiner --- src/packaging/markers.py | 4 +- tests/test_elffile.py | 10 +- tests/test_manylinux.py | 71 ++++++++----- tests/test_markers.py | 46 ++++---- tests/test_metadata.py | 118 +++++++++++---------- tests/test_musllinux.py | 20 +++- tests/test_specifiers.py | 183 ++++++++++++++++++++------------ tests/test_structures.py | 6 +- tests/test_tags.py | 219 +++++++++++++++++++++++---------------- tests/test_utils.py | 24 +++-- tests/test_version.py | 40 ++++--- 11 files changed, 452 insertions(+), 289 deletions(-) diff --git a/src/packaging/markers.py b/src/packaging/markers.py index 3d1e992f7..6654b5211 100644 --- a/src/packaging/markers.py +++ b/src/packaging/markers.py @@ -8,7 +8,7 @@ import os import platform import sys -from typing import AbstractSet, Any, Callable, Literal, TypedDict, Union, cast +from typing import AbstractSet, Any, Callable, Literal, Mapping, TypedDict, Union, cast from ._parser import MarkerAtom, MarkerList, Op, Value, Variable from ._parser import parse_marker as _parse_marker @@ -314,7 +314,7 @@ def __eq__(self, other: object) -> bool: def evaluate( self, - environment: dict[str, str] | None = None, + environment: Mapping[str, str | AbstractSet[str]] | None = None, context: EvaluateContext = "metadata", ) -> bool: """Evaluate a marker. diff --git a/tests/test_elffile.py b/tests/test_elffile.py index fd2ba25ec..678f1adb9 100644 --- a/tests/test_elffile.py +++ b/tests/test_elffile.py @@ -22,7 +22,9 @@ ("s390x-s390x", EIClass.C64, EIData.Msb, EMachine.S390), ], ) -def test_elffile_glibc(name, capacity, encoding, machine) -> None: +def test_elffile_glibc( + name: str, capacity: EIClass, encoding: EIData, machine: EMachine +) -> None: path = DIR_MANYLINUX.joinpath(f"hello-world-{name}") with path.open("rb") as f: ef = ELFFile(f) @@ -46,7 +48,9 @@ def test_elffile_glibc(name, capacity, encoding, machine) -> None: ("x86_64", EIClass.C64, EIData.Lsb, EMachine.X8664, "x86_64"), ], ) -def test_elffile_musl(name, capacity, encoding, machine, interpreter) -> None: +def test_elffile_musl( + name: str, capacity: EIClass, encoding: EIData, machine: EMachine, interpreter: str +) -> None: path = DIR_MUSLLINUX.joinpath(f"musl-{name}") with path.open("rb") as f: ef = ELFFile(f) @@ -68,7 +72,7 @@ def test_elffile_musl(name, capacity, encoding, machine, interpreter) -> None: ], ids=["no-magic", "wrong-magic", "unknown-format"], ) -def test_elffile_bad_ident(data) -> None: +def test_elffile_bad_ident(data: bytes) -> None: with pytest.raises(ELFInvalid): ELFFile(io.BytesIO(data)) diff --git a/tests/test_manylinux.py b/tests/test_manylinux.py index ffe7f39a2..9768fd06d 100644 --- a/tests/test_manylinux.py +++ b/tests/test_manylinux.py @@ -1,13 +1,19 @@ +from __future__ import annotations + try: import ctypes except ImportError: - ctypes = None + ctypes = None # type: ignore[assignment] import os import pathlib import platform import re import sys import types +import typing + +if typing.TYPE_CHECKING: + from collections.abc import Generator import pretend import pytest @@ -18,6 +24,7 @@ _glibc_version_string, _glibc_version_string_confstr, _glibc_version_string_ctypes, + _GLibCVersion, _is_compatible, _parse_elf, _parse_glibc_version, @@ -25,13 +32,13 @@ @pytest.fixture(autouse=True) -def clear_lru_cache(): +def clear_lru_cache() -> Generator[None, None, None]: yield _get_glibc_version.cache_clear() @pytest.fixture -def manylinux_module(monkeypatch: pytest.MonkeyPatch): +def manylinux_module(monkeypatch: pytest.MonkeyPatch) -> types.ModuleType: monkeypatch.setattr(_manylinux, "_get_glibc_version", lambda *args: (2, 20)) module_name = "_manylinux" module = types.ModuleType(module_name) @@ -44,11 +51,16 @@ def manylinux_module(monkeypatch: pytest.MonkeyPatch): ("attribute", "glibc"), [("1", (2, 5)), ("2010", (2, 12)), ("2014", (2, 17))] ) def test_module_declaration( - monkeypatch: pytest.MonkeyPatch, manylinux_module, attribute, glibc, tf + monkeypatch: pytest.MonkeyPatch, + manylinux_module: types.ModuleType, + attribute: str, + glibc: tuple[int, int], + tf: bool, ) -> None: manylinux = f"manylinux{attribute}_compatible" monkeypatch.setattr(manylinux_module, manylinux, tf, raising=False) - res = _is_compatible("x86_64", glibc) + glibc_version = _GLibCVersion(glibc[0], glibc[1]) + res = _is_compatible("x86_64", glibc_version) assert tf is res @@ -56,32 +68,37 @@ def test_module_declaration( ("attribute", "glibc"), [("1", (2, 5)), ("2010", (2, 12)), ("2014", (2, 17))] ) def test_module_declaration_missing_attribute( - monkeypatch: pytest.MonkeyPatch, manylinux_module, attribute, glibc -): + monkeypatch: pytest.MonkeyPatch, + manylinux_module: types.ModuleType, + attribute: str, + glibc: tuple[int, int], +) -> None: manylinux = f"manylinux{attribute}_compatible" monkeypatch.delattr(manylinux_module, manylinux, raising=False) - assert _is_compatible("x86_64", glibc) + glibc_version = _GLibCVersion(glibc[0], glibc[1]) + assert _is_compatible("x86_64", glibc_version) @pytest.mark.parametrize( ("version", "compatible"), [((2, 0), True), ((2, 5), True), ((2, 10), False)] ) def test_is_manylinux_compatible_glibc_support( - version, compatible, monkeypatch: pytest.MonkeyPatch + version: tuple[int, int], compatible: bool, monkeypatch: pytest.MonkeyPatch ) -> None: monkeypatch.setitem(sys.modules, "_manylinux", None) monkeypatch.setattr(_manylinux, "_get_glibc_version", lambda: (2, 5)) - assert bool(_is_compatible("any", version)) == compatible + glibc_version = _GLibCVersion(version[0], version[1]) + assert bool(_is_compatible("any", glibc_version)) == compatible @pytest.mark.parametrize("version_str", ["glibc-2.4.5", "2"]) -def test_check_glibc_version_warning(version_str) -> None: +def test_check_glibc_version_warning(version_str: str) -> None: msg = f"Expected glibc version with 2 components major.minor, got: {version_str}" with pytest.warns(RuntimeWarning, match=re.escape(msg)): _parse_glibc_version(version_str) -@pytest.mark.skipif(not ctypes, reason="requires ctypes") +@pytest.mark.skipif(not ctypes, reason="requires ctypes") # type: ignore[truthy-bool] @pytest.mark.parametrize( ("version_str", "expected"), [ @@ -91,17 +108,17 @@ def test_check_glibc_version_warning(version_str) -> None: ], ) def test_glibc_version_string( - version_str, expected, monkeypatch: pytest.MonkeyPatch + version_str: str | bytes, expected: str, monkeypatch: pytest.MonkeyPatch ) -> None: class LibcVersion: - def __init__(self, version_str): + def __init__(self, version_str: str | bytes) -> None: self.version_str = version_str - def __call__(self): - return version_str + def __call__(self) -> str | bytes: + return self.version_str class ProcessNamespace: - def __init__(self, libc_version): + def __init__(self, libc_version: LibcVersion) -> None: self.gnu_get_libc_version = libc_version process_namespace = ProcessNamespace(LibcVersion(version_str)) @@ -131,7 +148,7 @@ def test_glibc_version_string_fail(monkeypatch: pytest.MonkeyPatch) -> None: [pretend.raiser(ValueError), pretend.raiser(OSError), lambda _: "XXX"], ) def test_glibc_version_string_confstr_fail( - monkeypatch: pytest.MonkeyPatch, failure + monkeypatch: pytest.MonkeyPatch, failure: typing.Callable[[int], str | None] ) -> None: monkeypatch.setattr(os, "confstr", failure, raising=False) assert _glibc_version_string_confstr() is None @@ -151,7 +168,7 @@ def test_glibc_version_string_ctypes_missing(monkeypatch: pytest.MonkeyPatch) -> def test_glibc_version_string_ctypes_raise_oserror( monkeypatch: pytest.MonkeyPatch, ) -> None: - def patched_cdll(_name): + def patched_cdll(_name: str) -> None: raise OSError("Dynamic loading not supported") monkeypatch.setattr(ctypes, "CDLL", patched_cdll) @@ -162,27 +179,29 @@ def patched_cdll(_name): def test_is_manylinux_compatible_old() -> None: # Assuming no one is running this test with a version of glibc released in # 1997. - assert _is_compatible("any", (2, 0)) + assert _is_compatible("any", _GLibCVersion(2, 0)) def test_is_manylinux_compatible(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: "2.4") - assert _is_compatible("any", (2, 4)) + assert _is_compatible("any", _GLibCVersion(2, 4)) def test_glibc_version_string_none(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(_manylinux, "_glibc_version_string", lambda: None) - assert not _is_compatible("any", (2, 4)) + assert not _is_compatible("any", _GLibCVersion(2, 4)) @pytest.mark.parametrize( "content", [None, "invalid-magic", "invalid-class", "invalid-data", "too-short"] ) -def test_parse_elf_bad_executable(content) -> None: +def test_parse_elf_bad_executable(content: str | None) -> None: + path_str: str | None if content: path = pathlib.Path(__file__).parent / "manylinux" / f"hello-world-{content}" - path = os.fsdecode(path) + path_str = os.fsdecode(path) else: - path = None - with _parse_elf(path) as ef: + path_str = None + # None is not supported in the type annotation, but it was tested before. + with _parse_elf(path_str) as ef: # type: ignore[arg-type] assert ef is None diff --git a/tests/test_markers.py b/tests/test_markers.py index fa86921f3..b4815c525 100644 --- a/tests/test_markers.py +++ b/tests/test_markers.py @@ -2,6 +2,8 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations + import collections import itertools import os @@ -60,15 +62,15 @@ class TestNode: @pytest.mark.parametrize("value", ["one", "two", None, 3, 5, []]) - def test_accepts_value(self, value) -> None: - assert Node(value).value == value + def test_accepts_value(self, value: str | None | int | list[str]) -> None: + assert Node(value).value == value # type: ignore[arg-type] @pytest.mark.parametrize("value", ["one", "two"]) - def test_str(self, value) -> None: + def test_str(self, value: str) -> None: assert str(Node(value)) == str(value) @pytest.mark.parametrize("value", ["one", "two"]) - def test_repr(self, value) -> None: + def test_repr(self, value: str) -> None: assert repr(Node(value)) == f"" def test_base_class(self) -> None: @@ -141,11 +143,11 @@ def test_multidigit_minor_version(self, monkeypatch: pytest.MonkeyPatch) -> None def tests_when_releaselevel_final(self) -> None: v = FakeVersionInfo(3, 4, 2, "final", 0) - assert format_full_version(v) == "3.4.2" + assert format_full_version(v) == "3.4.2" # type: ignore[arg-type] def tests_when_releaselevel_not_final(self) -> None: v = FakeVersionInfo(3, 4, 2, "beta", 4) - assert format_full_version(v) == "3.4.2b4" + assert format_full_version(v) == "3.4.2b4" # type: ignore[arg-type] class TestMarker: @@ -160,7 +162,7 @@ class TestMarker: for i in itertools.product(VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_valid(self, marker_string) -> None: + def test_parses_valid(self, marker_string: str) -> None: Marker(marker_string) @pytest.mark.parametrize( @@ -174,7 +176,7 @@ def test_parses_valid(self, marker_string) -> None: '(python_version == "2.7") with random text', ], ) - def test_parses_invalid(self, marker_string) -> None: + def test_parses_invalid(self, marker_string: str) -> None: with pytest.raises(InvalidMarker): Marker(marker_string) @@ -213,7 +215,7 @@ def test_parses_invalid(self, marker_string) -> None: ), ], ) - def test_str_repr_eq_hash(self, marker_string, expected) -> None: + def test_str_repr_eq_hash(self, marker_string: str, expected: str) -> None: m = Marker(marker_string) assert str(m) == expected assert repr(m) == f"" @@ -248,7 +250,9 @@ def test_str_repr_eq_hash(self, marker_string, expected) -> None: ), ], ) - def test_different_markers_different_hashes(self, example1, example2) -> None: + def test_different_markers_different_hashes( + self, example1: str, example2: str + ) -> None: marker1, marker2 = Marker(example1), Marker(example2) # Markers created from strings that are not equivalent should differ. assert marker1 != marker2 @@ -316,8 +320,10 @@ def test_environment_with_extra_none(self) -> None: ), ], ) - def test_evaluates(self, marker_string, environment, expected) -> None: - args = [] if environment is None else [environment] + def test_evaluates( + self, marker_string: str, environment: dict[str, str] | None, expected: bool + ) -> None: + args = () if environment is None else (environment,) assert Marker(marker_string).evaluate(*args) == expected @pytest.mark.parametrize( @@ -331,7 +337,7 @@ def test_evaluates(self, marker_string, environment, expected) -> None: for i in itertools.product(PEP_345_VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_pep345_valid(self, marker_string) -> None: + def test_parses_pep345_valid(self, marker_string: str) -> None: Marker(marker_string) @pytest.mark.parametrize( @@ -354,9 +360,9 @@ def test_parses_pep345_valid(self, marker_string) -> None: ], ) def test_evaluate_pep345_markers( - self, marker_string, environment, expected + self, marker_string: str, environment: dict[str, str] | None, expected: bool ) -> None: - args = [] if environment is None else [environment] + args = () if environment is None else (environment,) assert Marker(marker_string).evaluate(*args) == expected @pytest.mark.parametrize( @@ -370,12 +376,12 @@ def test_evaluate_pep345_markers( for i in itertools.product(SETUPTOOLS_VARIABLES, OPERATORS, VALUES) ], ) - def test_parses_setuptools_legacy_valid(self, marker_string) -> None: + def test_parses_setuptools_legacy_valid(self, marker_string: str) -> None: Marker(marker_string) def test_evaluate_setuptools_legacy_markers(self) -> None: marker_string = "python_implementation=='Jython'" - args = [{"platform_python_implementation": "CPython"}] + args = ({"platform_python_implementation": "CPython"},) assert Marker(marker_string).evaluate(*args) is False def test_extra_str_normalization(self) -> None: @@ -414,12 +420,14 @@ def test_python_full_version_untagged(self) -> None: pytest.param('"Foo" in {0}', True, id="case-sensitive"), ], ) - def test_extras_and_dependency_groups(self, variable, expression, result) -> None: + def test_extras_and_dependency_groups( + self, variable: str, expression: str, result: bool + ) -> None: environment = {variable: {"foo", "bar"}} assert Marker(expression.format(variable)).evaluate(environment) == result @pytest.mark.parametrize("variable", ["extras", "dependency_groups"]) - def test_extras_and_dependency_groups_disallowed(self, variable) -> None: + def test_extras_and_dependency_groups_disallowed(self, variable: str) -> None: marker = Marker(f'"foo" in {variable}') assert not marker.evaluate(context="lock_file") diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 4b8dfb23f..db7e46eaa 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -8,12 +8,12 @@ import pytest from packaging import metadata, requirements, specifiers, utils, version -from packaging.metadata import ExceptionGroup +from packaging.metadata import ExceptionGroup, RawMetadata class TestRawMetadata: @pytest.mark.parametrize("raw_field", sorted(metadata._STRING_FIELDS)) - def test_non_repeating_fields_only_once(self, raw_field) -> None: + def test_non_repeating_fields_only_once(self, raw_field: str) -> None: data = "VaLuE" header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] single_header = f"{header_field}: {data}" @@ -21,10 +21,10 @@ def test_non_repeating_fields_only_once(self, raw_field) -> None: assert not unparsed assert len(raw) == 1 assert raw_field in raw - assert raw[raw_field] == data + assert raw[raw_field] == data # type: ignore[literal-required] @pytest.mark.parametrize("raw_field", sorted(metadata._STRING_FIELDS)) - def test_non_repeating_fields_repeated(self, raw_field) -> None: + def test_non_repeating_fields_repeated(self, raw_field: str) -> None: header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] data = "VaLuE" single_header = f"{header_field}: {data}" @@ -36,7 +36,7 @@ def test_non_repeating_fields_repeated(self, raw_field) -> None: assert unparsed[header_field] == [data] * 2 @pytest.mark.parametrize("raw_field", sorted(metadata._LIST_FIELDS)) - def test_repeating_fields_only_once(self, raw_field) -> None: + def test_repeating_fields_only_once(self, raw_field: str) -> None: data = "VaLuE" header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] single_header = f"{header_field}: {data}" @@ -44,10 +44,10 @@ def test_repeating_fields_only_once(self, raw_field) -> None: assert not unparsed assert len(raw) == 1 assert raw_field in raw - assert raw[raw_field] == [data] + assert raw[raw_field] == [data] # type: ignore[literal-required] @pytest.mark.parametrize("raw_field", sorted(metadata._LIST_FIELDS)) - def test_repeating_fields_repeated(self, raw_field) -> None: + def test_repeating_fields_repeated(self, raw_field: str) -> None: header_field = metadata._RAW_TO_EMAIL_MAPPING[raw_field] data = "VaLuE" single_header = f"{header_field}: {data}" @@ -56,7 +56,7 @@ def test_repeating_fields_repeated(self, raw_field) -> None: assert not unparsed assert len(raw) == 1 assert raw_field in raw - assert raw[raw_field] == [data] * 2 + assert raw[raw_field] == [data] * 2 # type: ignore[literal-required] @pytest.mark.parametrize( ("given", "expected"), @@ -71,7 +71,7 @@ def test_repeating_fields_repeated(self, raw_field) -> None: ("A B", ["A B"]), ], ) - def test_keywords(self, given, expected) -> None: + def test_keywords(self, given: str, expected: list[str]) -> None: header = f"Keywords: {given}" raw, unparsed = metadata.parse_email(header) assert not unparsed @@ -91,7 +91,7 @@ def test_keywords(self, given, expected) -> None: ("A,B,C", {"A": "B,C"}), ], ) - def test_project_urls_parsing(self, given, expected) -> None: + def test_project_urls_parsing(self, given: str, expected: dict[str, str]) -> None: header = f"project-url: {given}" raw, unparsed = metadata.parse_email(header) assert not unparsed @@ -139,7 +139,7 @@ def test_header_mojibake(self) -> None: assert unparsed[header_name] == [value] @pytest.mark.parametrize("given", ["hello", "description: hello", b"hello"]) - def test_description(self, given) -> None: + def test_description(self, given: str | bytes) -> None: raw, unparsed = metadata.parse_email(given) assert not unparsed assert len(raw) == 1 @@ -153,7 +153,8 @@ def test_description_non_utf8(self) -> None: assert not raw assert len(unparsed) == 1 assert "description" in unparsed - assert unparsed["description"] == [header_bytes] + # TODO: type annotations are not happy about this, investigate. + assert unparsed["description"] == [header_bytes] # type: ignore[comparison-overlap] @pytest.mark.parametrize( ("given", "expected"), @@ -163,7 +164,9 @@ def test_description_non_utf8(self) -> None: ("description: 1\ndescription: 2\n\n3", ["1", "2", "3"]), ], ) - def test_description_multiple(self, given, expected) -> None: + def test_description_multiple( + self, given: str | bytes, expected: list[str] + ) -> None: raw, unparsed = metadata.parse_email(given) assert not raw assert len(unparsed) == 1 @@ -266,7 +269,7 @@ def test_repr(self) -> None: assert individual_exception.__class__.__name__ in repr(exc) -_RAW_EXAMPLE = { +_RAW_EXAMPLE: RawMetadata = { "metadata_version": "2.5", "name": "packaging", "version": "2023.0.0", @@ -274,7 +277,14 @@ def test_repr(self) -> None: class TestMetadata: - def _invalid_with_cause(self, meta, attr, cause=None, *, field=None): + def _invalid_with_cause( + self, + meta: metadata.Metadata, + attr: str, + cause: type[BaseException] | None = None, + *, + field: str | None = None, + ) -> None: if field is None: field = attr with pytest.raises(metadata.InvalidMetadata) as exc_info: @@ -325,25 +335,26 @@ def test_required_fields(self) -> None: assert meta.metadata_version == _RAW_EXAMPLE["metadata_version"] @pytest.mark.parametrize("field", list(_RAW_EXAMPLE.keys())) - def test_required_fields_missing(self, field) -> None: + def test_required_fields_missing(self, field: str) -> None: required_fields = _RAW_EXAMPLE.copy() - del required_fields[field] + del required_fields[field] # type: ignore[misc] with pytest.raises(ExceptionGroup): metadata.Metadata.from_raw(required_fields) def test_raw_validate_unrecognized_field(self) -> None: - raw = { + raw: RawMetadata = { "metadata_version": "2.3", "name": "packaging", "version": "2023.0.0", } - # Safety check. - assert metadata.Metadata.from_raw(raw, validate=True) + # Safety check (always true) + assert metadata.Metadata.from_raw(raw, validate=True) # type: ignore[truthy-bool] - raw["dynamc"] = ["Obsoletes-Dist"] # Misspelled; missing an "i". + # Misspelled; missing an "i": + raw["dynamc"] = ["Obsoletes-Dist"] # type: ignore[typeddict-unknown-key] with pytest.raises(ExceptionGroup): metadata.Metadata.from_raw(raw, validate=True) @@ -370,19 +381,21 @@ def test_from_raw_validate(self) -> None: metadata.Metadata.from_raw(required_fields) @pytest.mark.parametrize("meta_version", ["2.2", "2.3"]) - def test_metadata_version_field_introduction(self, meta_version) -> None: - raw = { + def test_metadata_version_field_introduction(self, meta_version: str) -> None: + raw: RawMetadata = { "metadata_version": meta_version, "name": "packaging", "version": "2023.0.0", "dynamic": ["Obsoletes-Dist"], # Introduced in 2.2. } - assert metadata.Metadata.from_raw(raw, validate=True) + assert metadata.Metadata.from_raw(raw, validate=True) # type: ignore[truthy-bool] @pytest.mark.parametrize("meta_version", ["1.0", "1.1", "1.2", "2.1"]) - def test_metadata_version_field_introduction_mismatch(self, meta_version) -> None: - raw = { + def test_metadata_version_field_introduction_mismatch( + self, meta_version: str + ) -> None: + raw: RawMetadata = { "metadata_version": meta_version, "name": "packaging", "version": "2023.0.0", @@ -405,9 +418,9 @@ def test_metadata_version_field_introduction_mismatch(self, meta_version) -> Non "license", ], ) - def test_single_value_unvalidated_attribute(self, attribute) -> None: + def test_single_value_unvalidated_attribute(self, attribute: str) -> None: value = "Not important" - meta = metadata.Metadata.from_raw({attribute: value}, validate=False) + meta = metadata.Metadata.from_raw({attribute: value}, validate=False) # type: ignore[misc] assert getattr(meta, attribute) == value @@ -424,20 +437,20 @@ def test_single_value_unvalidated_attribute(self, attribute) -> None: "obsoletes", ], ) - def test_multi_value_unvalidated_attribute(self, attribute) -> None: + def test_multi_value_unvalidated_attribute(self, attribute: str) -> None: values = ["Not important", "Still not important"] - meta = metadata.Metadata.from_raw({attribute: values}, validate=False) + meta = metadata.Metadata.from_raw({attribute: values}, validate=False) # type: ignore[misc] assert getattr(meta, attribute) == values @pytest.mark.parametrize("version", ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]) - def test_valid_metadata_version(self, version) -> None: + def test_valid_metadata_version(self, version: str) -> None: meta = metadata.Metadata.from_raw({"metadata_version": version}, validate=False) assert meta.metadata_version == version @pytest.mark.parametrize("version", ["1.3", "2.0"]) - def test_invalid_metadata_version(self, version) -> None: + def test_invalid_metadata_version(self, version: str) -> None: meta = metadata.Metadata.from_raw({"metadata_version": version}, validate=False) with pytest.raises(metadata.InvalidMetadata): @@ -497,7 +510,7 @@ def test_invalid_name(self) -> None: "text/markdown; variant=CommonMark", ], ) - def test_valid_description_content_type(self, content_type) -> None: + def test_valid_description_content_type(self, content_type: str) -> None: meta = metadata.Metadata.from_raw( {"description_content_type": content_type}, validate=False ) @@ -514,7 +527,7 @@ def test_valid_description_content_type(self, content_type) -> None: "text/markdown; variant=commonmark", ], ) - def test_invalid_description_content_type(self, content_type) -> None: + def test_invalid_description_content_type(self, content_type: str) -> None: meta = metadata.Metadata.from_raw( {"description_content_type": content_type}, validate=False ) @@ -538,7 +551,7 @@ def test_valid_project_urls(self) -> None: assert meta.project_urls == urls @pytest.mark.parametrize("specifier", [">=3", ">2.6,!=3.0.*,!=3.1.*", "~=2.6"]) - def test_valid_requires_python(self, specifier) -> None: + def test_valid_requires_python(self, specifier: str) -> None: expected = specifiers.SpecifierSet(specifier) meta = metadata.Metadata.from_raw( {"requires_python": specifier}, validate=False @@ -619,7 +632,7 @@ def test_invalid_dynamic_value(self) -> None: meta.dynamic # noqa: B018 @pytest.mark.parametrize("field_name", ["name", "version", "metadata-version"]) - def test_disallowed_dynamic(self, field_name) -> None: + def test_disallowed_dynamic(self, field_name: str) -> None: meta = metadata.Metadata.from_raw({"dynamic": [field_name]}, validate=False) message = f"{field_name!r} is not allowed" @@ -634,7 +647,7 @@ def test_disallowed_dynamic(self, field_name) -> None: "field_name", sorted(metadata._RAW_TO_EMAIL_MAPPING.keys() - metadata._REQUIRED_ATTRS), ) - def test_optional_defaults_to_none(self, field_name) -> None: + def test_optional_defaults_to_none(self, field_name: str) -> None: meta = metadata.Metadata.from_raw({}, validate=False) assert getattr(meta, field_name) is None @@ -705,7 +718,9 @@ def test_optional_defaults_to_none(self, field_name) -> None: ("((MIT AND (MIT)))", "((MIT AND (MIT)))"), ], ) - def test_valid_license_expression(self, license_expression, expected) -> None: + def test_valid_license_expression( + self, license_expression: str, expected: str + ) -> None: meta = metadata.Metadata.from_raw( {"license_expression": license_expression}, validate=False ) @@ -745,7 +760,7 @@ def test_valid_license_expression(self, license_expression, expected) -> None: "mit with ( ) with ( ) or mit", ], ) - def test_invalid_license_expression(self, license_expression) -> None: + def test_invalid_license_expression(self, license_expression: str) -> None: meta = metadata.Metadata.from_raw( {"license_expression": license_expression}, validate=False ) @@ -761,7 +776,7 @@ def test_invalid_license_expression(self, license_expression) -> None: ["LICENSE"], ], ) - def test_valid_license_files(self, license_files) -> None: + def test_valid_license_files(self, license_files: list[str]) -> None: meta = metadata.Metadata.from_raw( {"license_files": license_files}, validate=False ) @@ -784,7 +799,7 @@ def test_valid_license_files(self, license_files) -> None: ["licenses\\LICENSE"], ], ) - def test_invalid_license_files(self, license_files) -> None: + def test_invalid_license_files(self, license_files: list[str]) -> None: meta = metadata.Metadata.from_raw( {"license_files": license_files}, validate=False ) @@ -793,31 +808,30 @@ def test_invalid_license_files(self, license_files) -> None: meta.license_files # noqa: B018 @pytest.mark.parametrize("key", ["import_namespaces", "import_names"]) - def test_valid_import_names(self, key) -> None: + def test_valid_import_names(self, key: str) -> None: import_names = [ "packaging", "packaging.metadata", "_utils ; private", "_stuff;private", ] - meta = metadata.Metadata.from_raw({key: import_names}, validate=False) - + meta = metadata.Metadata.from_raw({key: import_names}, validate=False) # type: ignore[misc] assert getattr(meta, key) == import_names @pytest.mark.parametrize("key", ["import_namespaces", "import_names"]) @pytest.mark.parametrize( "name", ["not-valid", "still.not-valid", "stuff;", "stuff; extra"] ) - def test_invalid_import_names_identifier(self, key, name) -> None: - meta = metadata.Metadata.from_raw({key: [name]}, validate=False) + def test_invalid_import_names_identifier(self, key: str, name: str) -> None: + meta = metadata.Metadata.from_raw({key: [name]}, validate=False) # type: ignore[misc] with pytest.raises(metadata.InvalidMetadata): getattr(meta, key) @pytest.mark.parametrize("key", ["import_namespaces", "import_names"]) - def test_invalid_import_names_keyword(self, key) -> None: + def test_invalid_import_names_keyword(self, key: str) -> None: import_names = ["class"] - meta = metadata.Metadata.from_raw({key: import_names}, validate=False) + meta = metadata.Metadata.from_raw({key: import_names}, validate=False) # type: ignore[misc] with pytest.raises(metadata.InvalidMetadata): getattr(meta, key) @@ -846,9 +860,9 @@ def test_write_metadata_with_description(self) -> None: written == "metadata-version: 2.3\nname: Hello\n" "version: 1.2.3\n\nHello\n\nWorld👋" ) - written = meta.as_rfc822().as_bytes() + written_bytes = meta.as_rfc822().as_bytes() assert ( - written + written_bytes == "metadata-version: 2.3\nname: Hello\n" "version: 1.2.3\n\nHello\n\nWorld👋".encode() ) @@ -867,9 +881,9 @@ def test_multiline_license(self) -> None: written == "metadata-version: 2.3\nname: packaging\nversion: 1.2.3" "\nlicense: Hello\n World🐍\n\n" ) - written = meta.as_rfc822().as_bytes() + written_bytes = meta.as_rfc822().as_bytes() assert ( - written + written_bytes == "metadata-version: 2.3\nname: packaging\nversion: 1.2.3" "\nlicense: Hello\n World🐍\n\n".encode() ) diff --git a/tests/test_musllinux.py b/tests/test_musllinux.py index 593b749e0..52964aec7 100644 --- a/tests/test_musllinux.py +++ b/tests/test_musllinux.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import collections import pathlib import subprocess +import typing import pretend import pytest @@ -8,6 +11,9 @@ from packaging import _musllinux from packaging._musllinux import _get_musl_version, _MuslVersion, _parse_musl_version +if typing.TYPE_CHECKING: + from collections.abc import Generator + MUSL_AMD64 = "musl libc (x86_64)\nVersion 1.2.2\n" MUSL_I386 = "musl libc (i386)\nVersion 1.2.1\n" MUSL_AARCH64 = "musl libc (aarch64)\nVersion 1.1.24\n" @@ -27,7 +33,7 @@ @pytest.fixture(autouse=True) -def clear_lru_cache(): +def clear_lru_cache() -> Generator[None, None, None]: yield _get_musl_version.cache_clear() @@ -43,7 +49,7 @@ def clear_lru_cache(): ], ids=["amd64-1.2.2", "i386-1.2.1", "aarch64-1.1.24", "invalid", "unknown"], ) -def test_parse_musl_version(output, version) -> None: +def test_parse_musl_version(output: str, version: _MuslVersion | None) -> None: assert _parse_musl_version(output) == version @@ -59,13 +65,17 @@ def test_parse_musl_version(output, version) -> None: ids=["does-not-exist", "glibc", "x86_64", "i386", "aarch64"], ) def test_get_musl_version( - monkeypatch: pytest.MonkeyPatch, executable, output, version, ld_musl + monkeypatch: pytest.MonkeyPatch, + executable: pathlib.Path, + output: str, + version: _MuslVersion | None, + ld_musl: str | None, ) -> None: - def mock_run(*args, **kwargs): + def mock_run(*args: object, **kwargs: object) -> tuple[object, ...]: return collections.namedtuple("Proc", "stderr")(output) run_recorder = pretend.call_recorder(mock_run) - monkeypatch.setattr(_musllinux.subprocess, "run", run_recorder) + monkeypatch.setattr(_musllinux.subprocess, "run", run_recorder) # type: ignore[attr-defined] assert _get_musl_version(str(executable)) == version diff --git a/tests/test_specifiers.py b/tests/test_specifiers.py index f20b9f2fa..3ab2523d5 100644 --- a/tests/test_specifiers.py +++ b/tests/test_specifiers.py @@ -2,9 +2,12 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations + import itertools import operator import re +import typing import pytest @@ -13,6 +16,9 @@ from .test_version import VERSIONS +if typing.TYPE_CHECKING: + from collections.abc import Callable + LEGACY_SPECIFIERS = [ "==2.1.0.3", "!=2.2.0.5", @@ -37,7 +43,7 @@ class TestSpecifier: @pytest.mark.parametrize("specifier", SPECIFIERS) - def test_specifiers_valid(self, specifier) -> None: + def test_specifiers_valid(self, specifier: str) -> None: Specifier(specifier) @pytest.mark.parametrize( @@ -84,7 +90,7 @@ def test_specifiers_valid(self, specifier) -> None: "!=1.0.dev1.*", ], ) - def test_specifiers_invalid(self, specifier) -> None: + def test_specifiers_invalid(self, specifier: str) -> None: with pytest.raises(InvalidSpecifier): Specifier(specifier) @@ -196,7 +202,7 @@ def test_specifiers_invalid(self, specifier) -> None: " \r \f \v v1.0\t\n", ], ) - def test_specifiers_normalized(self, version) -> None: + def test_specifiers_normalized(self, version: str) -> None: if "+" not in version: ops = ["~=", "==", "!=", "<=", ">=", "<", ">"] else: @@ -220,14 +226,14 @@ def test_specifiers_normalized(self, version) -> None: ("< 2", "<2"), ], ) - def test_specifiers_str_and_repr(self, specifier, expected) -> None: + def test_specifiers_str_and_repr(self, specifier: str, expected: str) -> None: spec = Specifier(specifier) assert str(spec) == expected assert repr(spec) == f"" @pytest.mark.parametrize("specifier", SPECIFIERS) - def test_specifiers_hash(self, specifier) -> None: + def test_specifiers_hash(self, specifier: str) -> None: assert hash(Specifier(specifier)) == hash(Specifier(specifier)) @pytest.mark.parametrize( @@ -243,13 +249,18 @@ def test_specifiers_hash(self, specifier) -> None: ] ), ) - def test_comparison_true(self, left, right, op) -> None: + def test_comparison_true( + self, + left: str, + right: str, + op: typing.Callable[[Specifier | str, Specifier | str], bool], + ) -> None: assert op(Specifier(left), Specifier(right)) assert op(left, Specifier(right)) assert op(Specifier(left), right) @pytest.mark.parametrize(("left", "right"), [("==2.8.0", "==2.8")]) - def test_comparison_canonicalizes(self, left, right) -> None: + def test_comparison_canonicalizes(self, left: str, right: str) -> None: assert Specifier(left) == Specifier(right) assert left == Specifier(right) assert Specifier(left) == right @@ -267,7 +278,12 @@ def test_comparison_canonicalizes(self, left, right) -> None: ] ), ) - def test_comparison_false(self, left, right, op) -> None: + def test_comparison_false( + self, + left: str, + right: str, + op: typing.Callable[[Specifier | str, Specifier | str], bool], + ) -> None: assert not op(Specifier(left), Specifier(right)) assert not op(left, Specifier(right)) assert not op(Specifier(left), right) @@ -279,7 +295,7 @@ def test_comparison_non_specifier(self) -> None: assert not Specifier("==1.0") == "12" @pytest.mark.parametrize( - ("version", "spec", "expected"), + ("version", "spec_str", "expected"), [ (v, s, True) for v, s in [ @@ -475,8 +491,8 @@ def test_comparison_non_specifier(self) -> None: ] ], ) - def test_specifiers(self, version, spec, expected) -> None: - spec = Specifier(spec, prereleases=True) + def test_specifiers(self, version: str, spec_str: str, expected: bool) -> None: + spec = Specifier(spec_str, prereleases=True) if expected: # Test that the plain string form works @@ -496,14 +512,14 @@ def test_specifiers(self, version, spec, expected) -> None: assert not spec.contains(Version(version)) @pytest.mark.parametrize( - ("spec", "version"), + ("spec_str", "version"), [ ("==1.0", "not a valid version"), ("===invalid", "invalid"), ], ) - def test_invalid_spec(self, spec, version) -> None: - spec = Specifier(spec, prereleases=True) + def test_invalid_spec(self, spec_str: str, version: str) -> None: + spec = Specifier(spec_str, prereleases=True) assert not spec.contains(version) @pytest.mark.parametrize( @@ -544,13 +560,13 @@ def test_invalid_spec(self, spec, version) -> None: ) def test_specifier_prereleases_set( self, - specifier, - initial_prereleases, - set_prereleases, - version, - initial_contains, - final_contains, - ): + specifier: str, + initial_prereleases: bool | None, + set_prereleases: bool | None, + version: str, + initial_contains: bool, + final_contains: bool, + ) -> None: """Test setting prereleases property.""" spec = Specifier(specifier, prereleases=initial_prereleases) @@ -563,7 +579,7 @@ def test_specifier_prereleases_set( assert spec.contains(version) == final_contains @pytest.mark.parametrize( - ("version", "spec", "expected"), + ("version", "spec_str", "expected"), [ ("1.0.0", "===1.0", False), ("1.0.dev0", "===1.0", False), @@ -572,8 +588,10 @@ def test_specifier_prereleases_set( ("1.0.dev0", "===1.0.dev0", True), ], ) - def test_specifiers_identity(self, version, spec, expected) -> None: - spec = Specifier(spec) + def test_specifiers_identity( + self, version: str, spec_str: str, expected: bool + ) -> None: + spec = Specifier(spec_str) if expected: # Identity comparisons only support the plain string form @@ -601,7 +619,9 @@ def test_specifiers_identity(self, version, spec, expected) -> None: ("~=1.0.dev1", True), ], ) - def test_specifier_prereleases_detection(self, specifier, expected) -> None: + def test_specifier_prereleases_detection( + self, specifier: str, expected: bool + ) -> None: assert Specifier(specifier).prereleases == expected @pytest.mark.parametrize( @@ -625,8 +645,13 @@ def test_specifier_prereleases_detection(self, specifier, expected) -> None: ], ) def test_specifiers_prereleases( - self, specifier, version, spec_pre, contains_pre, expected - ): + self, + specifier: str, + version: str, + spec_pre: bool | None, + contains_pre: bool | None, + expected: bool, + ) -> None: spec = Specifier(specifier, prereleases=spec_pre) assert spec.contains(version, prereleases=contains_pre) == expected @@ -660,8 +685,13 @@ def test_specifiers_prereleases( ], ) def test_specifier_filter( - self, specifier, specifier_prereleases, prereleases, input, expected - ): + self, + specifier: str, + specifier_prereleases: bool | None, + prereleases: bool | None, + input: list[str], + expected: list[str], + ) -> None: if specifier_prereleases is None: spec = Specifier(specifier) else: @@ -687,7 +717,7 @@ def test_specifier_filter( ("===lolwat", "==="), ], ) - def test_specifier_operator_property(self, spec, op) -> None: + def test_specifier_operator_property(self, spec: str, op: str) -> None: assert Specifier(spec).operator == op @pytest.mark.parametrize( @@ -706,19 +736,19 @@ def test_specifier_operator_property(self, spec, op) -> None: ("===lolwat", "lolwat"), ], ) - def test_specifier_version_property(self, spec, version) -> None: + def test_specifier_version_property(self, spec: str, version: str) -> None: assert Specifier(spec).version == version @pytest.mark.parametrize( - ("spec", "expected_length"), + ("spec_str", "expected_length"), [("", 0), ("==2.0", 1), (">=2.0", 1), (">=2.0,<3", 2), (">=2.0,<3,==2.4", 3)], ) - def test_length(self, spec, expected_length) -> None: - spec = SpecifierSet(spec) + def test_length(self, spec_str: str, expected_length: int) -> None: + spec = SpecifierSet(spec_str) assert len(spec) == expected_length @pytest.mark.parametrize( - ("spec", "expected_items"), + ("spec_str", "expected_items"), [ ("", []), ("==2.0", ["==2.0"]), @@ -727,8 +757,8 @@ def test_length(self, spec, expected_length) -> None: (">=2.0,<3,==2.4", [">=2.0", "<3", "==2.4"]), ], ) - def test_iteration(self, spec, expected_items) -> None: - spec = SpecifierSet(spec) + def test_iteration(self, spec_str: str, expected_items: list[str]) -> None: + spec = SpecifierSet(spec_str) items = {str(item) for item in spec} assert items == set(expected_items) @@ -741,7 +771,7 @@ def test_specifier_hash_for_compatible_operator(self) -> None: class TestSpecifierSet: @pytest.mark.parametrize("version", VERSIONS) - def test_empty_specifier(self, version) -> None: + def test_empty_specifier(self, version: str) -> None: spec = SpecifierSet(prereleases=True) assert version in spec @@ -802,13 +832,13 @@ def test_create_from_specifiers(self) -> None: ) def test_specifier_prereleases_explicit( self, - initial_prereleases, - set_prereleases, - version, - initial_contains, - final_contains, - spec_str, - ): + initial_prereleases: bool | None, + set_prereleases: bool | None, + version: str, + initial_contains: bool, + final_contains: bool, + spec_str: str, + ) -> None: """Test setting prereleases property with different initial states.""" spec = SpecifierSet(spec_str, prereleases=initial_prereleases) @@ -897,13 +927,13 @@ def test_specifier_contains_prereleases(self) -> None: ) def test_specifier_contains_installed_prereleases( self, - specifier, - version, - spec_prereleases, - contains_prereleases, - installed, - expected, - ): + specifier: str, + version: str, + spec_prereleases: bool | None, + contains_prereleases: bool | None, + installed: bool | None, + expected: bool, + ) -> None: """Test the behavior of SpecifierSet.contains with installed and prereleases.""" spec = SpecifierSet(specifier, prereleases=spec_prereleases) @@ -976,8 +1006,13 @@ def test_specifier_contains_installed_prereleases( ], ) def test_specifier_filter( - self, specifier, specifier_prereleases, prereleases, input, expected - ): + self, + specifier: str, + specifier_prereleases: bool | None, + prereleases: bool | None, + input: list[str], + expected: list[str], + ) -> None: if specifier_prereleases is None: spec = SpecifierSet(specifier) else: @@ -1209,7 +1244,11 @@ def test_specifier_filter( ], ) def test_filter_exclusionary_bridges( - self, specifier, prereleases, input, expected + self, + specifier: str, + prereleases: bool | None, + input: list[str], + expected: list[str], ) -> None: """ Test that filter correctly handles exclusionary bridges. @@ -1333,8 +1372,8 @@ def test_filter_exclusionary_bridges( ], ) def test_contains_exclusionary_bridges( - self, specifier, prereleases, version, expected - ): + self, specifier: str, prereleases: bool | None, version: str, expected: bool + ) -> None: """ Test that contains correctly handles exclusionary bridges. @@ -1353,7 +1392,9 @@ def test_contains_exclusionary_bridges( (">=1.0", "not a valid version"), ], ) - def test_contains_rejects_invalid_specifier(self, specifier, input) -> None: + def test_contains_rejects_invalid_specifier( + self, specifier: str, input: str + ) -> None: spec = SpecifierSet(specifier, prereleases=True) assert not spec.contains(input) @@ -1375,20 +1416,20 @@ def test_contains_rejects_invalid_specifier(self, specifier, input) -> None: ("!=2.0 ,>1.0", "!=2.0,>1.0"), ], ) - def test_specifiers_str_and_repr(self, specifier, expected) -> None: + def test_specifiers_str_and_repr(self, specifier: str, expected: str) -> None: spec = SpecifierSet(specifier) assert str(spec) == expected assert repr(spec) == f"" @pytest.mark.parametrize("specifier", SPECIFIERS + LEGACY_SPECIFIERS) - def test_specifiers_hash(self, specifier) -> None: + def test_specifiers_hash(self, specifier: str) -> None: assert hash(SpecifierSet(specifier)) == hash(SpecifierSet(specifier)) @pytest.mark.parametrize( ("left", "right", "expected"), [(">2.0", "<5.0", ">2.0,<5.0")] ) - def test_specifiers_combine(self, left, right, expected) -> None: + def test_specifiers_combine(self, left: str, right: str, expected: str) -> None: result = SpecifierSet(left) & SpecifierSet(right) assert result == SpecifierSet(expected) @@ -1445,7 +1486,7 @@ def test_specifiers_combine(self, left, right, expected) -> None: def test_specifiers_combine_not_implemented(self) -> None: with pytest.raises(TypeError): - SpecifierSet() & 12 + SpecifierSet() & 12 # type: ignore[operator] @pytest.mark.parametrize( ("left", "right", "op"), @@ -1460,7 +1501,9 @@ def test_specifiers_combine_not_implemented(self) -> None: ] ), ) - def test_comparison_true(self, left, right, op) -> None: + def test_comparison_true( + self, left: str, right: str, op: Callable[[object, object], bool] + ) -> None: assert op(SpecifierSet(left), SpecifierSet(right)) assert op(SpecifierSet(left), Specifier(right)) assert op(Specifier(left), SpecifierSet(right)) @@ -1480,7 +1523,9 @@ def test_comparison_true(self, left, right, op) -> None: ] ), ) - def test_comparison_false(self, left, right, op) -> None: + def test_comparison_false( + self, left: str, right: str, op: Callable[[object, object], bool] + ) -> None: assert not op(SpecifierSet(left), SpecifierSet(right)) assert not op(SpecifierSet(left), Specifier(right)) assert not op(Specifier(left), SpecifierSet(right)) @@ -1488,7 +1533,7 @@ def test_comparison_false(self, left, right, op) -> None: assert not op(SpecifierSet(left), right) @pytest.mark.parametrize(("left", "right"), [("==2.8.0", "==2.8")]) - def test_comparison_canonicalizes(self, left, right) -> None: + def test_comparison_canonicalizes(self, left: str, right: str) -> None: assert SpecifierSet(left) == SpecifierSet(right) assert left == SpecifierSet(right) assert SpecifierSet(left) == right @@ -1508,7 +1553,9 @@ def test_comparison_non_specifier(self) -> None: ("1.0.0+local", ">1.0.0", False), ], ) - def test_comparison_ignores_local(self, version, specifier, expected) -> None: + def test_comparison_ignores_local( + self, version: str, specifier: str, expected: bool + ) -> None: assert (Version(version) in SpecifierSet(specifier)) == expected def test_contains_with_compatible_operator(self) -> None: @@ -1532,8 +1579,8 @@ def test_contains_with_compatible_operator(self) -> None: ], ) def test_arbitrary_equality_is_intersection_preserving( - self, spec1, spec2, input_versions - ): + self, spec1: str, spec2: str, input_versions: list[str] + ) -> None: """ In general we expect for two specifiers s1 and s2, that the two statements are equivalent: diff --git a/tests/test_structures.py b/tests/test_structures.py index 3665d97f3..d85c96215 100644 --- a/tests/test_structures.py +++ b/tests/test_structures.py @@ -2,6 +2,8 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations + import pytest from packaging._structures import Infinity, NegativeInfinity @@ -24,7 +26,7 @@ def test_negative_infinity_hash() -> None: @pytest.mark.parametrize("left", [1, "a", ("b", 4)]) -def test_infinity_comparison(left) -> None: +def test_infinity_comparison(left: int | str | tuple[str, int]) -> None: assert left < Infinity assert left <= Infinity assert not left == Infinity @@ -34,7 +36,7 @@ def test_infinity_comparison(left) -> None: @pytest.mark.parametrize("left", [1, "a", ("b", 4)]) -def test_negative_infinity_lesser(left) -> None: +def test_negative_infinity_lesser(left: int | str | tuple[str, int]) -> None: assert not left < NegativeInfinity assert not left <= NegativeInfinity assert not left == NegativeInfinity diff --git a/tests/test_tags.py b/tests/test_tags.py index 83a479dd0..735fb8cde 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations import collections.abc import subprocess @@ -9,7 +10,7 @@ try: import ctypes except ImportError: - ctypes = None + ctypes = None # type: ignore[assignment] import importlib import os import pathlib @@ -19,6 +20,7 @@ import sys import sysconfig import types +import typing import pretend import pytest @@ -27,15 +29,18 @@ from packaging._manylinux import _GLibCVersion from packaging._musllinux import _MuslVersion +if typing.TYPE_CHECKING: + from collections.abc import Callable + @pytest.fixture -def example_tag(): +def example_tag() -> tags.Tag: return tags.Tag("py3", "none", "any") @pytest.fixture -def manylinux_module(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda *args: (2, 20)) +def manylinux_module(monkeypatch: pytest.MonkeyPatch) -> types.ModuleType: + monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda *args: (2, 20)) # type: ignore[attr-defined] module_name = "_manylinux" module = types.ModuleType(module_name) monkeypatch.setitem(sys.modules, module_name, module) @@ -43,8 +48,8 @@ def manylinux_module(monkeypatch: pytest.MonkeyPatch): @pytest.fixture -def mock_interpreter_name(monkeypatch: pytest.MonkeyPatch): - def mock(name): +def mock_interpreter_name(monkeypatch: pytest.MonkeyPatch) -> Callable[[str], bool]: + def mock(name: str) -> bool: name = name.lower() if sys.implementation.name != name: monkeypatch.setattr(sys.implementation, "name", name) @@ -55,7 +60,7 @@ def mock(name): @pytest.fixture -def mock_ios(monkeypatch: pytest.MonkeyPatch): +def mock_ios(monkeypatch: pytest.MonkeyPatch) -> None: # Monkeypatch the platform to be iOS monkeypatch.setattr(sys, "platform", "ios") @@ -69,17 +74,17 @@ def mock_ios(monkeypatch: pytest.MonkeyPatch): ) # Mock the return value of platform.ios_ver. - def mock_ios_ver(*args): + def mock_ios_ver(*args: object) -> tuple[str, str, str, bool]: return ("iOS", "13.2", "iPhone15,2", False) if sys.version_info < (3, 13): - platform.ios_ver = mock_ios_ver + platform.ios_ver = mock_ios_ver # type: ignore[attr-defined] else: monkeypatch.setattr(platform, "ios_ver", mock_ios_ver) @pytest.fixture -def mock_android(monkeypatch: pytest.MonkeyPatch): +def mock_android(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(sys, "platform", "android") monkeypatch.setattr(platform, "system", lambda: "Android") monkeypatch.setattr(sysconfig, "get_platform", lambda: "android-21-arm64_v8a") @@ -109,33 +114,33 @@ def test_equality(self) -> None: def test_equality_fails_with_non_tag(self) -> None: assert not tags.Tag("py3", "none", "any") == "non-tag" - def test_hashing(self, example_tag) -> None: + def test_hashing(self, example_tag: tags.Tag) -> None: tags = {example_tag} # Should not raise TypeError. assert example_tag in tags - def test_hash_equality(self, example_tag) -> None: + def test_hash_equality(self, example_tag: tags.Tag) -> None: equal_tag = tags.Tag("py3", "none", "any") assert example_tag == equal_tag # Sanity check. assert example_tag.__hash__() == equal_tag.__hash__() - def test_str(self, example_tag) -> None: + def test_str(self, example_tag: tags.Tag) -> None: assert str(example_tag) == "py3-none-any" - def test_repr(self, example_tag) -> None: + def test_repr(self, example_tag: tags.Tag) -> None: assert repr(example_tag) == f"" - def test_attribute_access(self, example_tag) -> None: + def test_attribute_access(self, example_tag: tags.Tag) -> None: assert example_tag.interpreter == "py3" assert example_tag.abi == "none" assert example_tag.platform == "any" class TestParseTag: - def test_simple(self, example_tag) -> None: + def test_simple(self, example_tag: tags.Tag) -> None: parsed_tags = tags.parse_tag(str(example_tag)) assert parsed_tags == {example_tag} - def test_multi_interpreter(self, example_tag) -> None: + def test_multi_interpreter(self, example_tag: tags.Tag) -> None: expected = {example_tag, tags.Tag("py2", "none", "any")} given = tags.parse_tag("py2.py3-none-any") assert given == expected @@ -164,11 +169,13 @@ class MockImplementation: pass mock_implementation = MockImplementation() - mock_implementation.name = "sillywalk" + mock_implementation.name = "sillywalk" # type: ignore[attr-defined] monkeypatch.setattr(sys, "implementation", mock_implementation, raising=False) assert tags.interpreter_name() == "sillywalk" - def test_interpreter_short_names(self, mock_interpreter_name) -> None: + def test_interpreter_short_names( + self, mock_interpreter_name: Callable[[str], bool] + ) -> None: mock_interpreter_name("cpython") assert tags.interpreter_name() == "cp" @@ -176,11 +183,11 @@ def test_interpreter_short_names(self, mock_interpreter_name) -> None: class TestInterpreterVersion: def test_warn(self, monkeypatch: pytest.MonkeyPatch) -> None: class MockConfigVar: - def __init__(self, return_): - self.warn = None + def __init__(self, return_: str) -> None: + self.warn: bool | None = None self._return = return_ - def __call__(self, _name, warn): + def __call__(self, _name: str, warn: bool = False) -> str: self.warn = warn return self._return @@ -204,7 +211,10 @@ def test_python_version_nodot(self, monkeypatch: pytest.MonkeyPatch) -> None: ], ) def test_sys_version_info( - self, version_info, version_str, monkeypatch: pytest.MonkeyPatch + self, + version_info: tuple[int, int, int], + version_str: str, + monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr(tags, "_get_config_var", lambda *args, **kwargs: None) monkeypatch.setattr(sys, "version_info", version_info) @@ -223,7 +233,7 @@ class TestMacOSPlatforms: ("ppc64", True, "ppc"), ], ) - def test_architectures(self, arch, is_32bit, expected) -> None: + def test_architectures(self, arch: str, is_32bit: bool, expected: str) -> None: assert tags._mac_arch(arch, is_32bit=is_32bit) == expected @pytest.mark.parametrize( @@ -265,7 +275,9 @@ def test_architectures(self, arch, is_32bit, expected) -> None: ((12, 0), "arm64", ["arm64", "universal2"]), ], ) - def test_binary_formats(self, version, arch, expected) -> None: + def test_binary_formats( + self, version: tuple[int, int], arch: str, expected: list[str] + ) -> None: assert tags._mac_binary_formats(version, arch) == expected def test_version_detection(self, monkeypatch: pytest.MonkeyPatch) -> None: @@ -317,7 +329,7 @@ def test_version_detection_compatibility( assert not platforms[0].startswith(unexpected) @pytest.mark.parametrize("arch", ["x86_64", "i386"]) - def test_arch_detection(self, arch, monkeypatch: pytest.MonkeyPatch) -> None: + def test_arch_detection(self, arch: str, monkeypatch: pytest.MonkeyPatch) -> None: if platform.system() != "Darwin" or platform.mac_ver()[2] != arch: monkeypatch.setattr( platform, "mac_ver", lambda: ("10.14", ("", "", ""), arch) @@ -347,7 +359,7 @@ def test_mac_platforms(self) -> None: assert not list(tags.mac_platforms((10, 0), "x86_64")) @pytest.mark.parametrize(("major", "minor"), [(11, 0), (11, 3), (12, 0), (12, 3)]) - def test_macos_11(self, major, minor) -> None: + def test_macos_11(self, major: int, minor: int) -> None: platforms = list(tags.mac_platforms((major, minor), "x86_64")) assert "macosx_11_0_arm64" not in platforms assert "macosx_11_0_x86_64" in platforms @@ -527,9 +539,9 @@ def test_abi(self) -> None: class TestManylinuxPlatform: - def teardown_method(self): + def teardown_method(self) -> None: # Clear the version cache - tags._manylinux._get_glibc_version.cache_clear() + tags._manylinux._get_glibc_version.cache_clear() # type: ignore[attr-defined] def test_get_config_var_does_not_log(self, monkeypatch: pytest.MonkeyPatch) -> None: debug = pretend.call_recorder(lambda *a: None) @@ -558,11 +570,15 @@ def test_get_config_var_does_log(self, monkeypatch: pytest.MonkeyPatch) -> None: ], ) def test_linux_platforms_32_64bit_on_64bit_os( - self, arch, is_32bit, expected, monkeypatch: pytest.MonkeyPatch - ): + self, + arch: str, + is_32bit: bool, + expected: list[str], + monkeypatch: pytest.MonkeyPatch, + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: arch) monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) - monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) + monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) # type: ignore[attr-defined] linux_platform = list(tags._linux_platforms(is_32bit=is_32bit))[ -len(expected) : ] @@ -573,13 +589,13 @@ def test_linux_platforms_manylinux_unsupported( ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr(os, "confstr", lambda _: "glibc 2.20", raising=False) - monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) + monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) # type: ignore[attr-defined] linux_platform = list(tags._linux_platforms(is_32bit=False)) assert linux_platform == ["linux_x86_64"] def test_linux_platforms_manylinux1(self, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( - tags._manylinux, + tags._manylinux, # type: ignore[attr-defined] "_is_compatible", lambda _, glibc_version: glibc_version == _GLibCVersion(2, 5), ) @@ -649,11 +665,11 @@ def test_linux_platforms_manylinux2014( [("armv7l", "armv7l"), ("armv8l", "armv8l"), ("aarch64", "armv8l")], ) def test_linux_platforms_manylinux2014_armhf_abi( - self, native_arch, cross_arch, monkeypatch: pytest.MonkeyPatch - ): - monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.30") + self, native_arch: str, cross_arch: str, monkeypatch: pytest.MonkeyPatch + ) -> None: + monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.30") # type: ignore[attr-defined] monkeypatch.setattr( - tags._manylinux, + tags._manylinux, # type: ignore[attr-defined] "_is_compatible", lambda _, glibc_version: glibc_version == _GLibCVersion(2, 17), ) @@ -678,7 +694,7 @@ def test_linux_platforms_manylinux2014_armhf_abi( def test_linux_platforms_manylinux2014_i386_abi( self, monkeypatch: pytest.MonkeyPatch ) -> None: - monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.17") + monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.17") # type: ignore[attr-defined] monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr( sys, @@ -715,8 +731,8 @@ def test_linux_platforms_manylinux_glibc3( self, monkeypatch: pytest.MonkeyPatch ) -> None: # test for a future glic 3.x version - monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "3.2") - monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: True) + monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "3.2") # type: ignore[attr-defined] + monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: True) # type: ignore[attr-defined] monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_aarch64") monkeypatch.setattr( sys, @@ -748,27 +764,27 @@ def test_linux_platforms_manylinux_glibc3( def test_linux_platforms_musllinux( self, monkeypatch: pytest.MonkeyPatch, - native_arch, - cross32_arch, - musl_version, - cross32, - ): + native_arch: str, + cross32_arch: str, + musl_version: _MuslVersion, + cross32: bool, + ) -> None: fake_executable = str( pathlib.Path(__file__) .parent.joinpath("musllinux", f"musl-{native_arch}") .resolve() ) - monkeypatch.setattr(tags._musllinux.sys, "executable", fake_executable) + monkeypatch.setattr(tags._musllinux.sys, "executable", fake_executable) # type: ignore[attr-defined] monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{native_arch}") - monkeypatch.setattr(tags._manylinux, "platform_tags", lambda *_: ()) + monkeypatch.setattr(tags._manylinux, "platform_tags", lambda *_: ()) # type: ignore[attr-defined] recorder = pretend.call_recorder(lambda _: musl_version) - monkeypatch.setattr(tags._musllinux, "_get_musl_version", recorder) + monkeypatch.setattr(tags._musllinux, "_get_musl_version", recorder) # type: ignore[attr-defined] platforms = list(tags._linux_platforms(is_32bit=cross32)) target_arch = cross32_arch if cross32 else native_arch archs = {"armv8l": ["armv8l", "armv7l"]}.get(target_arch, [target_arch]) - expected = [] + expected: list[str] = [] for arch in archs: expected.extend( f"musllinux_{musl_version[0]}_{minor}_{arch}" @@ -783,7 +799,7 @@ def test_linux_platforms_manylinux2014_armv6l( self, monkeypatch: pytest.MonkeyPatch ) -> None: monkeypatch.setattr( - tags._manylinux, + tags._manylinux, # type: ignore[attr-defined] "_is_compatible", lambda _, glibc_version: glibc_version == _GLibCVersion(2, 17), ) @@ -798,9 +814,9 @@ def test_linux_platforms_manylinux2014_armv6l( [("x86_64", "x32", "i686"), ("armv7l", "armel", "armv7l")], ) def test_linux_platforms_not_manylinux_abi( - self, monkeypatch: pytest.MonkeyPatch, machine, abi, alt_machine - ): - monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) + self, monkeypatch: pytest.MonkeyPatch, machine: str, abi: str, alt_machine: str + ) -> None: + monkeypatch.setattr(tags._manylinux, "_is_compatible", lambda *args: False) # type: ignore[attr-defined] monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{machine}") monkeypatch.setattr( sys, @@ -834,12 +850,12 @@ def test_linux_not_linux(self, monkeypatch: pytest.MonkeyPatch) -> None: ], ) def test_platform_tags( - platform_name, dispatch_func, monkeypatch: pytest.MonkeyPatch + platform_name: str, dispatch_func: str, monkeypatch: pytest.MonkeyPatch ) -> None: expected = ["sillywalk"] monkeypatch.setattr(platform, "system", lambda: platform_name) monkeypatch.setattr(tags, dispatch_func, lambda: expected) - assert tags.platform_tags() == expected + assert list(tags.platform_tags()) == expected def test_platform_tags_space(monkeypatch: pytest.MonkeyPatch) -> None: @@ -855,7 +871,11 @@ class TestCPythonABI: [(1, False, True), (0, False, False), (None, True, True)], ) def test_debug( - self, py_debug, gettotalrefcount, result, monkeypatch: pytest.MonkeyPatch + self, + py_debug: int | None, + gettotalrefcount: bool, + result: bool, + monkeypatch: pytest.MonkeyPatch, ) -> None: config = {"Py_DEBUG": py_debug, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -875,7 +895,7 @@ def test_debug_file_extension(self, monkeypatch: pytest.MonkeyPatch) -> None: ("debug", "expected"), [(True, ["cp38d", "cp38"]), (False, ["cp38"])] ) def test__debug_cp38( - self, debug, expected, monkeypatch: pytest.MonkeyPatch + self, debug: int | None, expected: list[str], monkeypatch: pytest.MonkeyPatch ) -> None: config = {"Py_DEBUG": debug} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -891,7 +911,11 @@ def test__debug_cp38( ], ) def test_pymalloc( - self, pymalloc, version, result, monkeypatch: pytest.MonkeyPatch + self, + pymalloc: int | None, + version: tuple[int, int], + result: bool, + monkeypatch: pytest.MonkeyPatch, ) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": pymalloc, "Py_UNICODE_SIZE": 2} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -910,7 +934,12 @@ def test_pymalloc( ], ) def test_wide_unicode( - self, unicode_size, maxunicode, version, result, monkeypatch: pytest.MonkeyPatch + self, + unicode_size: int | None, + maxunicode: int, + version: tuple[int, int], + result: bool, + monkeypatch: pytest.MonkeyPatch, ) -> None: config = {"Py_DEBUG": 0, "WITH_PYMALLOC": 0, "Py_UNICODE_SIZE": unicode_size} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -1060,7 +1089,7 @@ def test_major_only_python_version_with_default_abis(self) -> None: assert result == [tags.Tag("cp3", "none", "plat")] @pytest.mark.parametrize("abis", [[], ["abi3"], ["none"]]) - def test_skip_redundant_abis(self, abis) -> None: + def test_skip_redundant_abis(self, abis: list[str]) -> None: results = list(tags.cpython_tags((3, 0), abis=abis, platforms=["any"])) assert results == [tags.Tag("cp30", "none", "any")] @@ -1144,7 +1173,7 @@ def test__generic_abi_none(self, monkeypatch: pytest.MonkeyPatch) -> None: @pytest.mark.parametrize("ext_suffix", ["invalid", None]) def test__generic_abi_error( - self, ext_suffix, monkeypatch: pytest.MonkeyPatch + self, ext_suffix: str | None, monkeypatch: pytest.MonkeyPatch ) -> None: config = {"EXT_SUFFIX": ext_suffix} monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__) @@ -1210,7 +1239,7 @@ def test_all_args(self) -> None: ] @pytest.mark.parametrize("abi", [[], ["none"]]) - def test_abi_unspecified(self, abi) -> None: + def test_abi_unspecified(self, abi: list[str]) -> None: no_abi = list(tags.generic_tags("sillywalk34", abi, ["plat1", "plat2"])) assert no_abi == [ tags.Tag("sillywalk34", "none", "plat1"), @@ -1389,15 +1418,17 @@ def test_default_platforms(self, monkeypatch: pytest.MonkeyPatch) -> None: class TestSysTags: - def teardown_method(self): + def teardown_method(self) -> None: # Clear the version cache - tags._glibc_version = [] + tags._glibc_version = [] # type: ignore[attr-defined] @pytest.mark.parametrize( ("name", "expected"), [("CPython", "cp"), ("PyPy", "pp"), ("Jython", "jy"), ("IronPython", "ip")], ) - def test_interpreter_name(self, name, expected, mock_interpreter_name) -> None: + def test_interpreter_name( + self, name: str, expected: str, mock_interpreter_name: Callable[[str], bool] + ) -> None: mock_interpreter_name(name) assert tags.interpreter_name() == expected @@ -1405,7 +1436,9 @@ def test_iterator(self) -> None: assert isinstance(tags.sys_tags(), collections.abc.Iterator) def test_mac_cpython( - self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + self, + mock_interpreter_name: Callable[[str], bool], + monkeypatch: pytest.MonkeyPatch, ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) @@ -1424,7 +1457,9 @@ def test_mac_cpython( ) def test_windows_cpython( - self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + self, + mock_interpreter_name: Callable[[str], bool], + monkeypatch: pytest.MonkeyPatch, ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) @@ -1444,7 +1479,9 @@ def test_windows_cpython( assert result[-1] == expected def test_linux_cpython( - self, mock_interpreter_name, monkeypatch: pytest.MonkeyPatch + self, + mock_interpreter_name: Callable[[str], bool], + monkeypatch: pytest.MonkeyPatch, ) -> None: if mock_interpreter_name("CPython"): monkeypatch.setattr(tags, "_cpython_abis", lambda *a: ["cp33m"]) @@ -1483,10 +1520,10 @@ def test_linux_platforms_manylinux2014_armv6l( assert platforms == expected def test_skip_manylinux_2014( - self, monkeypatch: pytest.MonkeyPatch, manylinux_module + self, monkeypatch: pytest.MonkeyPatch, manylinux_module: types.ModuleType ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_ppc64") - monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 20)) + monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 20)) # type: ignore[attr-defined] monkeypatch.setattr( manylinux_module, "manylinux2014_compatible", False, raising=False ) @@ -1507,8 +1544,8 @@ def test_skip_manylinux_2014( [("x86_64", "x32", "i686"), ("armv7l", "armel", "armv7l")], ) def test_linux_platforms_not_manylinux_abi( - self, monkeypatch: pytest.MonkeyPatch, machine, abi, alt_machine - ): + self, monkeypatch: pytest.MonkeyPatch, machine: str, abi: str, alt_machine: str + ) -> None: monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{machine}") monkeypatch.setattr( sys, @@ -1530,19 +1567,19 @@ def test_linux_platforms_not_manylinux_abi( def test_linux_use_manylinux_compatible( self, monkeypatch: pytest.MonkeyPatch, - manylinux_module, - machine, - major, - minor, - tf, - ): - def manylinux_compatible(tag_major, tag_minor, tag_arch): + manylinux_module: types.ModuleType, + machine: str, + major: int, + minor: int, + tf: bool, + ) -> None: + def manylinux_compatible(tag_major: int, tag_minor: int, tag_arch: str) -> bool: if tag_major == 2 and tag_minor == 22: return tag_arch == "s390x" return False monkeypatch.setattr( - tags._manylinux, + tags._manylinux, # type: ignore[attr-defined] "_get_glibc_version", lambda: (major, minor), ) @@ -1559,14 +1596,18 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): assert platforms == expected def test_linux_use_manylinux_compatible_none( - self, monkeypatch: pytest.MonkeyPatch, manylinux_module + self, monkeypatch: pytest.MonkeyPatch, manylinux_module: types.ModuleType ) -> None: - def manylinux_compatible(tag_major, tag_minor, tag_arch): # noqa: ARG001 + def manylinux_compatible( + tag_major: int, + tag_minor: int, + tag_arch: str, # noqa: ARG001 + ) -> bool | None: if tag_major == 2 and tag_minor < 25: return False return None - monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 30)) + monkeypatch.setattr(tags._manylinux, "_get_glibc_version", lambda: (2, 30)) # type: ignore[attr-defined] monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_x86_64") monkeypatch.setattr( manylinux_module, @@ -1612,7 +1653,7 @@ def test_cpython_first_none_any_tag(self, monkeypatch: pytest.MonkeyPatch) -> No class TestBitness: - def teardown_method(self): + def teardown_method(self) -> None: importlib.reload(tags) @pytest.mark.parametrize( @@ -1627,9 +1668,13 @@ def teardown_method(self): ], ) def test_32bit_interpreter( - self, maxsize, sizeof_voidp, expected, monkeypatch: pytest.MonkeyPatch + self, + maxsize: int, + sizeof_voidp: int, + expected: bool, + monkeypatch: pytest.MonkeyPatch, ) -> None: - def _calcsize(fmt): + def _calcsize(fmt: str) -> int: assert fmt == "P" return sizeof_voidp diff --git a/tests/test_utils.py b/tests/test_utils.py index d18c6e7c2..2f269edc1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,6 +2,8 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations + import pytest from packaging.tags import Tag @@ -33,7 +35,7 @@ ("foo----bar", "foo-bar"), ], ) -def test_canonicalize_name(name, expected) -> None: +def test_canonicalize_name(name: str, expected: str) -> None: assert canonicalize_name(name) == expected @@ -49,7 +51,7 @@ def test_canonicalize_name(name, expected) -> None: ("h\ri", "h\ri"), ], ) -def test_canonicalize_name_invalid(name, expected) -> None: +def test_canonicalize_name_invalid(name: str, expected: str) -> None: with pytest.raises(InvalidName): canonicalize_name(name, validate=True) assert canonicalize_name(name) == expected @@ -70,7 +72,7 @@ def test_canonicalize_name_invalid(name, expected) -> None: ("foo----bar", "foo-bar"), ], ) -def test_is_normalized_name(name, expected) -> None: +def test_is_normalized_name(name: str, expected: str) -> None: assert is_normalized_name(expected) if name != expected: assert not is_normalized_name(name) @@ -95,12 +97,12 @@ def test_is_normalized_name(name, expected) -> None: ("1.0.1-test7", "1.0.1-test7"), ], ) -def test_canonicalize_version(version, expected) -> None: +def test_canonicalize_version(version: str, expected: str) -> None: assert canonicalize_version(version) == expected @pytest.mark.parametrize(("version"), ["1.4.0", "1.0"]) -def test_canonicalize_version_no_strip_trailing_zero(version) -> None: +def test_canonicalize_version_no_strip_trailing_zero(version: str) -> None: assert canonicalize_version(version, strip_trailing_zero=False) == version @@ -151,8 +153,10 @@ def test_canonicalize_version_no_strip_trailing_zero(version) -> None: ), ], ) -def test_parse_wheel_filename(filename, name, version, build, tags) -> None: - assert parse_wheel_filename(filename) == (name, version, build, tags) +def test_parse_wheel_filename( + filename: str, name: str, version: Version, build: tuple[int, str], tags: set[Tag] +) -> None: + assert parse_wheel_filename(filename) == (name, version, build, frozenset(tags)) @pytest.mark.parametrize( @@ -168,7 +172,7 @@ def test_parse_wheel_filename(filename, name, version, build, tags) -> None: ("foo-1.0-200-py3-none-any-junk.whl"), # Too many dashes (`-junk`) ], ) -def test_parse_wheel_invalid_filename(filename) -> None: +def test_parse_wheel_invalid_filename(filename: str) -> None: with pytest.raises(InvalidWheelFilename): parse_wheel_filename(filename) @@ -177,7 +181,7 @@ def test_parse_wheel_invalid_filename(filename) -> None: ("filename", "name", "version"), [("foo-1.0.tar.gz", "foo", Version("1.0")), ("foo-1.0.zip", "foo", Version("1.0"))], ) -def test_parse_sdist_filename(filename, name, version) -> None: +def test_parse_sdist_filename(filename: str, name: str, version: Version) -> None: assert parse_sdist_filename(filename) == (name, version) @@ -189,6 +193,6 @@ def test_parse_sdist_filename(filename, name, version) -> None: ("foo-1.x.tar.gz"), # Invalid version ], ) -def test_parse_sdist_invalid_filename(filename) -> None: +def test_parse_sdist_invalid_filename(filename: str) -> None: with pytest.raises(InvalidSdistFilename): parse_sdist_filename(filename) diff --git a/tests/test_version.py b/tests/test_version.py index 8c672866b..61350fbb8 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -2,14 +2,20 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +from __future__ import annotations + import itertools import operator +import typing import pretend import pytest from packaging.version import InvalidVersion, Version, parse +if typing.TYPE_CHECKING: + from collections.abc import Callable + def test_parse() -> None: assert isinstance(parse("1.0"), Version) @@ -317,7 +323,7 @@ def test_version_hash(self, version: str) -> None: ("1!1.0.post5+deadbeef", "1!1.0.post5"), ], ) - def test_version_public(self, version, public) -> None: + def test_version_public(self, version: str, public: str) -> None: assert Version(version).public == public @pytest.mark.parametrize( @@ -354,7 +360,7 @@ def test_version_public(self, version, public) -> None: ("1!1.0.post5+deadbeef", "1!1.0"), ], ) - def test_version_base_version(self, version, base_version) -> None: + def test_version_base_version(self, version: str, base_version: str) -> None: assert Version(version).base_version == base_version @pytest.mark.parametrize( @@ -391,7 +397,7 @@ def test_version_base_version(self, version, base_version) -> None: ("1!1.0.post5+deadbeef", 1), ], ) - def test_version_epoch(self, version, epoch) -> None: + def test_version_epoch(self, version: str, epoch: int) -> None: assert Version(version).epoch == epoch @pytest.mark.parametrize( @@ -428,7 +434,7 @@ def test_version_epoch(self, version, epoch) -> None: ("1!1.0.post5+deadbeef", (1, 0)), ], ) - def test_version_release(self, version, release) -> None: + def test_version_release(self, version: str, release: tuple[int, int]) -> None: assert Version(version).release == release @pytest.mark.parametrize( @@ -465,7 +471,7 @@ def test_version_release(self, version, release) -> None: ("1!1.0.post5+deadbeef", "deadbeef"), ], ) - def test_version_local(self, version, local) -> None: + def test_version_local(self, version: str, local: str | None) -> None: assert Version(version).local == local @pytest.mark.parametrize( @@ -502,7 +508,7 @@ def test_version_local(self, version, local) -> None: ("1!1.0.post5+deadbeef", None), ], ) - def test_version_pre(self, version, pre) -> None: + def test_version_pre(self, version: str, pre: None | tuple[str, int]) -> None: assert Version(version).pre == pre @pytest.mark.parametrize( @@ -532,7 +538,7 @@ def test_version_pre(self, version, pre) -> None: ("1.0.post1+dev", False), ], ) - def test_version_is_prerelease(self, version, expected) -> None: + def test_version_is_prerelease(self, version: str, expected: bool) -> None: assert Version(version).is_prerelease is expected @pytest.mark.parametrize( @@ -569,7 +575,7 @@ def test_version_is_prerelease(self, version, expected) -> None: ("1!1.0.post5+deadbeef", None), ], ) - def test_version_dev(self, version, dev) -> None: + def test_version_dev(self, version: str, dev: int | None) -> None: assert Version(version).dev == dev @pytest.mark.parametrize( @@ -606,7 +612,7 @@ def test_version_dev(self, version, dev) -> None: ("1!1.0.post5+deadbeef", False), ], ) - def test_version_is_devrelease(self, version, expected) -> None: + def test_version_is_devrelease(self, version: str, expected: bool) -> None: assert Version(version).is_devrelease is expected @pytest.mark.parametrize( @@ -643,7 +649,7 @@ def test_version_is_devrelease(self, version, expected) -> None: ("1!1.0.post5+deadbeef", 5), ], ) - def test_version_post(self, version, post) -> None: + def test_version_post(self, version: str, post: int | None) -> None: assert Version(version).post == post @pytest.mark.parametrize( @@ -656,7 +662,7 @@ def test_version_post(self, version, post) -> None: ("1.0.post1", True), ], ) - def test_version_is_postrelease(self, version, expected) -> None: + def test_version_is_postrelease(self, version: str, expected: bool) -> None: assert Version(version).is_postrelease is expected @pytest.mark.parametrize( @@ -698,7 +704,9 @@ def test_version_is_postrelease(self, version, expected) -> None: ] ), ) - def test_comparison_true(self, left, right, op) -> None: + def test_comparison_true( + self, left: str, right: str, op: Callable[[Version, Version], bool] + ) -> None: assert op(Version(left), Version(right)) @pytest.mark.parametrize( @@ -740,16 +748,18 @@ def test_comparison_true(self, left, right, op) -> None: ] ), ) - def test_comparison_false(self, left, right, op) -> None: + def test_comparison_false( + self, left: str, right: str, op: Callable[[Version, Version], bool] + ) -> None: assert not op(Version(left), Version(right)) @pytest.mark.parametrize("op", ["lt", "le", "eq", "ge", "gt", "ne"]) - def test_dunder_op_returns_notimplemented(self, op) -> None: + def test_dunder_op_returns_notimplemented(self, op: str) -> None: method = getattr(Version, f"__{op}__") assert method(Version("1"), 1) is NotImplemented @pytest.mark.parametrize(("op", "expected"), [("eq", False), ("ne", True)]) - def test_compare_other(self, op, expected) -> None: + def test_compare_other(self, op: str, expected: bool) -> None: other = pretend.stub(**{f"__{op}__": lambda _: NotImplemented}) assert getattr(operator, op)(Version("1"), other) is expected