From 8c6aed505d0711c004ff614d0a16234fe1cfe014 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 16:14:40 -0600 Subject: [PATCH 01/13] tests: add FixtureFactory fixture --- tests/conftest.py | 30 ++++++++++++++++++++++++++++++ tests/types.py | 12 ++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/types.py diff --git a/tests/conftest.py b/tests/conftest.py index 30e87fcd3..4a1b640d9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ from __future__ import annotations +import shutil import sys import tempfile @@ -18,6 +19,9 @@ if TYPE_CHECKING: from _pytest.config import Config from _pytest.config.argparsing import Parser + from _pytest.fixtures import FixtureRequest + + from tests.types import FixtureFactory def pytest_addoption(parser: Parser) -> None: @@ -37,6 +41,32 @@ def pytest_configure(config: Config) -> None: config.option.markexpr = "not integration" +@pytest.fixture +def fixture_factory(request: FixtureRequest, tmp_path: Path) -> FixtureFactory: + """Provides a factory function that creates a copy of a fixture in a temporary directory.""" + test_root = Path(__file__).parent + + def _factory(name: str, scope: Path | None = None) -> Path: + if scope is None: + # If scope is None, find "fixtures/" relative to the test. + scope = request.path.parent.relative_to(test_root) + + source = test_root / scope / "fixtures" / name + target = tmp_path / name + + if not source.exists(): + raise FileNotFoundError(source) + + if source.is_dir(): + shutil.copytree(source, target) + else: + shutil.copyfile(source, target) + + return target + + return _factory + + def get_project_from_dir(base_directory: Path) -> Callable[[str], Path]: def get(name: str) -> Path: path = base_directory / name diff --git a/tests/types.py b/tests/types.py new file mode 100644 index 000000000..acc510ee7 --- /dev/null +++ b/tests/types.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING +from typing import Protocol + + +if TYPE_CHECKING: + from pathlib import Path + + +class FixtureFactory(Protocol): + def __call__(self, name: str, scope: Path | None = None) -> Path: ... From 02969e1c6ea746628df8e7506117d6d6adc3518e Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 19:55:00 -0600 Subject: [PATCH 02/13] tests/masonry/builders: enable parallelism Use a clean copy of the fixtures each run to allow these tests to run in parallel; and correct mistakes/mistesting found along the way. --- .../{puplic => public}/item1/itemdata1.txt | 0 .../item1/subitem/subitemdata.txt | 0 .../{puplic => public}/item2/itemdata2.txt | 0 .../{puplic => public}/publicdata.txt | 0 tests/masonry/builders/test_builder.py | 149 +++-- tests/masonry/builders/test_complete.py | 280 ++++----- tests/masonry/builders/test_sdist.py | 365 ++++++------ tests/masonry/builders/test_wheel.py | 534 +++++++++--------- 8 files changed, 632 insertions(+), 696 deletions(-) rename tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/{puplic => public}/item1/itemdata1.txt (100%) rename tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/{puplic => public}/item1/subitem/subitemdata.txt (100%) rename tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/{puplic => public}/item2/itemdata2.txt (100%) rename tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/{puplic => public}/publicdata.txt (100%) diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/itemdata1.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item1/itemdata1.txt similarity index 100% rename from tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/itemdata1.txt rename to tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item1/itemdata1.txt diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/subitem/subitemdata.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item1/subitem/subitemdata.txt similarity index 100% rename from tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item1/subitem/subitemdata.txt rename to tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item1/subitem/subitemdata.txt diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item2/itemdata2.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item2/itemdata2.txt similarity index 100% rename from tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/item2/itemdata2.txt rename to tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/item2/itemdata2.txt diff --git a/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/publicdata.txt b/tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/publicdata.txt similarity index 100% rename from tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/puplic/publicdata.txt rename to tests/masonry/builders/fixtures/exclude_nested_data_toml/my_package/public/publicdata.txt diff --git a/tests/masonry/builders/test_builder.py b/tests/masonry/builders/test_builder.py index f01325d7e..798dfeb36 100644 --- a/tests/masonry/builders/test_builder.py +++ b/tests/masonry/builders/test_builder.py @@ -15,25 +15,28 @@ if TYPE_CHECKING: from pytest_mock import MockerFixture + from tests.types import FixtureFactory + + +def test_building_not_possible_in_non_package_mode( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("non_package_mode", scope=Path("")) -def test_building_not_possible_in_non_package_mode() -> None: with pytest.raises(RuntimeError) as err: - Builder( - Factory().create_poetry( - Path(__file__).parent.parent.parent / "fixtures" / "non_package_mode" - ) - ) + Builder(Factory().create_poetry(fixture)) assert str(err.value) == "Building a package is not possible in non-package mode." -def test_builder_find_excluded_files(mocker: MockerFixture) -> None: +def test_builder_find_excluded_files( + fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] - builder = Builder( - Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete") - ) + fixture = fixture_factory("complete") + builder = Builder(Factory().create_poetry(fixture)) assert builder.find_excluded_files() == {"my_package/sub_pkg1/extra_file.xml"} @@ -42,15 +45,14 @@ def test_builder_find_excluded_files(mocker: MockerFixture) -> None: sys.platform == "win32", reason="Windows is case insensitive for the most part", ) -def test_builder_find_case_sensitive_excluded_files(mocker: MockerFixture) -> None: +def test_builder_find_case_sensitive_excluded_files( + fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] - builder = Builder( - Factory().create_poetry( - Path(__file__).parent / "fixtures" / "case_sensitive_exclusions" - ) - ) + fixture = fixture_factory("case_sensitive_exclusions") + builder = Builder(Factory().create_poetry(fixture)) assert builder.find_excluded_files() == { "my_package/FooBar/Bar.py", @@ -68,24 +70,21 @@ def test_builder_find_case_sensitive_excluded_files(mocker: MockerFixture) -> No reason="Windows is case insensitive for the most part", ) def test_builder_find_invalid_case_sensitive_excluded_files( + fixture_factory: FixtureFactory, mocker: MockerFixture, ) -> None: p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") p.return_value = [] - builder = Builder( - Factory().create_poetry( - Path(__file__).parent / "fixtures" / "invalid_case_sensitive_exclusions" - ) - ) + fixture = fixture_factory("invalid_case_sensitive_exclusions") + builder = Builder(Factory().create_poetry(fixture)) assert {"my_package/Bar/foo/bar/Foo.py"} == builder.find_excluded_files() -def test_get_metadata_content() -> None: - builder = Builder( - Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete") - ) +def test_get_metadata_content(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + builder = Builder(Factory().create_poetry(fixture)) metadata = builder.get_metadata_content() @@ -139,32 +138,27 @@ def test_get_metadata_content() -> None: ] -def test_metadata_pretty_name() -> None: - builder = Builder( - Factory().create_poetry(Path(__file__).parent / "fixtures" / "Pretty.Name") - ) +def test_metadata_pretty_name(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("Pretty.Name") + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) assert metadata["Name"] == "Pretty.Name" -def test_metadata_homepage_default() -> None: - builder = Builder( - Factory().create_poetry(Path(__file__).parent / "fixtures" / "simple_version") - ) +def test_metadata_homepage_default(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("simple_version") + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) assert metadata["Home-page"] is None -def test_metadata_with_vcs_dependencies() -> None: - builder = Builder( - Factory().create_poetry( - Path(__file__).parent / "fixtures" / "with_vcs_dependency" - ) - ) +def test_metadata_with_vcs_dependencies(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("with_vcs_dependency") + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) @@ -173,12 +167,9 @@ def test_metadata_with_vcs_dependencies() -> None: assert requires_dist == "cleo @ git+https://github.com/sdispater/cleo.git@master" -def test_metadata_with_url_dependencies() -> None: - builder = Builder( - Factory().create_poetry( - Path(__file__).parent / "fixtures" / "with_url_dependency" - ) - ) +def test_metadata_with_url_dependencies(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("with_url_dependency") + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) @@ -190,12 +181,9 @@ def test_metadata_with_url_dependencies() -> None: ) -def test_missing_script_files_throws_error() -> None: - builder = Builder( - Factory().create_poetry( - Path(__file__).parent / "fixtures" / "script_reference_file_missing" - ) - ) +def test_missing_script_files_throws_error(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("script_reference_file_missing") + builder = Builder(Factory().create_poetry(fixture)) with pytest.raises(RuntimeError) as err: builder.convert_script_files() @@ -203,22 +191,18 @@ def test_missing_script_files_throws_error() -> None: assert "is not found." in str(err.value) -def test_invalid_script_files_definition() -> None: +def test_invalid_script_files_definition(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("script_reference_file_invalid_definition") + with pytest.raises(RuntimeError) as err: - Builder( - Factory().create_poetry( - Path(__file__).parent - / "fixtures" - / "script_reference_file_invalid_definition" - ) - ) + Builder(Factory().create_poetry(fixture)) assert "configuration is invalid" in str(err.value) assert "scripts.invalid_definition" in str(err.value) @pytest.mark.parametrize( - "fixture, result", + "fixture_name, expected_result", [ ( "script_callable_legacy_string", @@ -241,16 +225,18 @@ def test_invalid_script_files_definition() -> None: ) @pytest.mark.filterwarnings("ignore:.* script .* extra:DeprecationWarning") def test_builder_convert_entry_points( - fixture: str, result: dict[str, list[str]] + fixture_name: str, + expected_result: dict[str, list[str]], + fixture_factory: FixtureFactory, ) -> None: - entry_points = Builder( - Factory().create_poetry(Path(__file__).parent / "fixtures" / fixture) - ).convert_entry_points() - assert entry_points == result + fixture = fixture_factory(fixture_name) + + entry_points = Builder(Factory().create_poetry(fixture)).convert_entry_points() + assert entry_points == expected_result @pytest.mark.parametrize( - "fixture, result", + "fixture_name, expected_result", [ ( "script_callable_legacy_table", @@ -270,20 +256,23 @@ def test_builder_convert_entry_points( ), ], ) -def test_builder_convert_script_files(fixture: str, result: list[Path]) -> None: - project_root = Path(__file__).parent / "fixtures" / fixture - script_files = Builder(Factory().create_poetry(project_root)).convert_script_files() - assert [p.relative_to(project_root) for p in script_files] == result +def test_builder_convert_script_files( + fixture_name: str, expected_result: list[Path], fixture_factory: FixtureFactory +) -> None: + fixture = fixture_factory(fixture_name) + + script_files = Builder(Factory().create_poetry(fixture)).convert_script_files() + assert [p.relative_to(fixture) for p in script_files] == expected_result -def test_metadata_with_readme_files() -> None: - test_path = Path(__file__).parent.parent.parent / "fixtures" / "with_readme_files" - builder = Builder(Factory().create_poetry(test_path)) +def test_metadata_with_readme_files(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("with_readme_files", scope=Path("")) + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) - readme1 = test_path / "README-1.rst" - readme2 = test_path / "README-2.rst" + readme1 = fixture / "README-1.rst" + readme2 = fixture / "README-2.rst" description = "\n".join( [readme1.read_text(encoding="utf-8"), readme2.read_text(encoding="utf-8"), ""] ) @@ -291,11 +280,11 @@ def test_metadata_with_readme_files() -> None: assert metadata.get_payload() == description -def test_metadata_with_wildcard_dependency_constraint() -> None: - test_path = ( - Path(__file__).parent / "fixtures" / "with_wildcard_dependency_constraint" - ) - builder = Builder(Factory().create_poetry(test_path)) +def test_metadata_with_wildcard_dependency_constraint( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("with_wildcard_dependency_constraint") + builder = Builder(Factory().create_poetry(fixture)) metadata = Parser().parsestr(builder.get_metadata_content()) diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py index 46bb9fd54..90ae00219 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -4,15 +4,12 @@ import os import platform import re -import shutil import sys import tarfile -import tempfile import zipfile from pathlib import Path from typing import TYPE_CHECKING -from typing import Iterator import pytest @@ -26,52 +23,39 @@ if TYPE_CHECKING: from pytest_mock import MockerFixture -fixtures_dir = Path(__file__).parent / "fixtures" - - -@pytest.fixture(autouse=True) -def setup() -> Iterator[None]: - clear_samples_dist() - - yield - - clear_samples_dist() - - -def clear_samples_dist() -> None: - for dist in fixtures_dir.glob("**/dist"): - if dist.is_dir(): - shutil.rmtree(str(dist)) + from tests.types import FixtureFactory @pytest.mark.skipif( platform.python_implementation().lower() == "pypy", reason="Disable test for PyPy" ) @pytest.mark.parametrize( - ["project", "exptected_c_dir"], + ["fixture_name", "exptected_c_dir"], [ ("extended", "extended"), ("extended_with_no_setup", "extended"), ("src_extended", "src/extended"), ], ) -def test_wheel_c_extension(project: str, exptected_c_dir: str) -> None: - module_path = fixtures_dir / project - poetry = Factory().create_poetry(module_path) +def test_wheel_c_extension( + fixture_name: str, exptected_c_dir: str, fixture_factory: FixtureFactory +) -> None: + fixture = fixture_factory(fixture_name) + poetry = Factory().create_poetry(fixture) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = fixtures_dir / project / "dist" / "extended-0.1.tar.gz" + sdist = fixture / "dist" / "extended-0.1.tar.gz" assert sdist.exists() with tarfile.open(sdist, "r") as tar: assert "extended-0.1/build.py" in tar.getnames() assert f"extended-0.1/{exptected_c_dir}/extended.c" in tar.getnames() - whl = next(iter((module_path / "dist").glob("extended-0.1-cp*-cp*-*.whl"))) - assert whl.exists() + bdist = next(iter((fixture / "dist").glob("extended-0.1-cp*-cp*-*.whl"))) + assert bdist.exists() - with zipfile.ZipFile(whl) as zipf: + with zipfile.ZipFile(bdist) as zipf: has_compiled_extension = False for name in zipf.namelist(): if name.startswith("extended/extended") and name.endswith((".so", ".pyd")): @@ -102,26 +86,18 @@ def test_wheel_c_extension(project: str, exptected_c_dir: str) -> None: assert len(set(record_files)) == len(record_files) -@pytest.mark.parametrize("no_vcs", [False, True]) -def test_complete(no_vcs: bool) -> None: - module_path = fixtures_dir / "complete" +def test_complete(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") - if no_vcs: - # Copy the complete fixtures dir to a temporary directory - temporary_dir = Path(tempfile.mkdtemp()) / "complete" - shutil.copytree(module_path.as_posix(), temporary_dir.as_posix()) - module_path = temporary_dir - - poetry = Factory().create_poetry(module_path) + poetry = Factory().create_poetry(fixture) with pytest.warns(DeprecationWarning, match=".* script .* extra"): SdistBuilder(poetry).build() WheelBuilder(poetry).build() - whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl" - - assert whl.exists() + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() if sys.platform != "win32": - assert (os.stat(str(whl)).st_mode & 0o777) == 0o644 + assert (os.stat(bdist).st_mode & 0o777) == 0o644 expected_name_list = [ "my_package/__init__.py", @@ -146,7 +122,7 @@ def test_complete(no_vcs: bool) -> None: "my_package-1.2.3.dist-info/RECORD", ] - with zipfile.ZipFile(str(whl)) as zipf: + with zipfile.ZipFile(bdist) as zipf: assert zipf.namelist() == expected_name_list assert ( "Hello World" @@ -228,182 +204,168 @@ def test_complete(no_vcs: bool) -> None: assert actual_files == expected_name_list -def test_module_src() -> None: - module_path = fixtures_dir / "source_file" - poetry = Factory().create_poetry(module_path) +def test_module_src(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_file") + poetry = Factory().create_poetry(fixture) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = module_path / "dist" / "module_src-0.1.tar.gz" - + sdist = fixture / "dist" / "module_src-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "module_src-0.1/src/module_src.py" in tar.getnames() - whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl" + bdist = fixture / "dist" / "module_src-0.1-py2.py3-none-any.whl" + assert bdist.exists() - assert whl.exists() - - with zipfile.ZipFile(str(whl)) as zipf: + with zipfile.ZipFile(bdist) as zipf: assert "module_src.py" in zipf.namelist() -def test_package_src() -> None: - module_path = fixtures_dir / "source_package" - poetry = Factory().create_poetry(module_path) +def test_package_src(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_package") + poetry = Factory().create_poetry(fixture) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = module_path / "dist" / "package_src-0.1.tar.gz" - + sdist = fixture / "dist" / "package_src-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "package_src-0.1/src/package_src/module.py" in tar.getnames() - whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl" - - assert whl.exists() + bdist = fixture / "dist" / "package_src-0.1-py2.py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as zipf: + with zipfile.ZipFile(bdist) as zipf: assert "package_src/__init__.py" in zipf.namelist() assert "package_src/module.py" in zipf.namelist() -def test_split_source() -> None: - module_path = fixtures_dir / "split_source" - poetry = Factory().create_poetry(module_path) +def test_split_source(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("split_source") + poetry = Factory().create_poetry(fixture) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = module_path / "dist" / "split_source-0.1.tar.gz" - + sdist = fixture / "dist" / "split_source-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "split_source-0.1/lib_a/module_a/__init__.py" in tar.getnames() assert "split_source-0.1/lib_b/module_b/__init__.py" in tar.getnames() - whl = module_path / "dist" / "split_source-0.1-py3-none-any.whl" - - assert whl.exists() + bdist = fixture / "dist" / "split_source-0.1-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as zipf: + with zipfile.ZipFile(bdist) as zipf: assert "module_a/__init__.py" in zipf.namelist() assert "module_b/__init__.py" in zipf.namelist() -def test_package_with_include(mocker: MockerFixture) -> None: - module_path = fixtures_dir / "with-include" +def test_package_with_include( + fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: + class MockGit: + def get_ignored_files(self, folder: Path | None = None) -> list[str]: + # Patch git module to return specific excluded files + return [ + "extra_dir/vcs_excluded.txt", + "extra_dir/sub_pkg/vcs_excluded.txt", + ] - # Patch git module to return specific excluded files - p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files") - p.return_value = [ - str( - Path(__file__).parent - / "fixtures" - / "with-include" - / "extra_dir" - / "vcs_excluded.txt" - ), - str( - Path(__file__).parent - / "fixtures" - / "with-include" - / "extra_dir" - / "sub_pkg" - / "vcs_excluded.txt" - ), - ] + p = mocker.patch("poetry.core.vcs.get_vcs") + p.return_value = MockGit() + + fixture = fixture_factory("with-include") + poetry = Factory().create_poetry(fixture) - poetry = Factory().create_poetry(module_path) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = fixtures_dir / "with-include" / "dist" / "with_include-1.2.3.tar.gz" - + sdist = fixture / "dist" / "with_include-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: - names = tar.getnames() - assert len(names) == len(set(names)) - assert "with_include-1.2.3/LICENSE" in names - assert "with_include-1.2.3/README.rst" in names - assert "with_include-1.2.3/extra_dir/__init__.py" in names - assert "with_include-1.2.3/extra_dir/vcs_excluded.txt" in names - assert "with_include-1.2.3/extra_dir/sub_pkg/__init__.py" in names - assert "with_include-1.2.3/extra_dir/sub_pkg/vcs_excluded.txt" not in names - assert "with_include-1.2.3/my_module.py" in names - assert "with_include-1.2.3/notes.txt" in names - assert "with_include-1.2.3/package_with_include/__init__.py" in names - assert "with_include-1.2.3/tests/__init__.py" in names - assert "with_include-1.2.3/pyproject.toml" in names - assert "with_include-1.2.3/PKG-INFO" in names - assert "with_include-1.2.3/for_wheel_only/__init__.py" not in names - assert "with_include-1.2.3/src/src_package/__init__.py" in names - assert "with_include-1.2.3/etc/from_to/__init__.py" in names - - whl = module_path / "dist" / "with_include-1.2.3-py3-none-any.whl" - - assert whl.exists() - - with zipfile.ZipFile(str(whl)) as z: - names = z.namelist() - assert len(names) == len(set(names)) - assert "with_include-1.2.3.dist-info/LICENSE" in names - assert "extra_dir/__init__.py" in names - assert "extra_dir/vcs_excluded.txt" in names - assert "extra_dir/sub_pkg/__init__.py" in names - assert "extra_dir/sub_pkg/vcs_excluded.txt" not in names - assert "for_wheel_only/__init__.py" in names - assert "my_module.py" in names - assert "notes.txt" in names - assert "package_with_include/__init__.py" in names - assert "tests/__init__.py" not in names - assert "src_package/__init__.py" in names - assert "target_from_to/from_to/__init__.py" in names - assert "target_module/my_module_to.py" in names - - -def test_respect_format_for_explicit_included_files() -> None: - module_path = fixtures_dir / "exclude-whl-include-sdist" - poetry = Factory().create_poetry(module_path) + assert p.called + + with tarfile.open(sdist, "r") as tar: + assert "with_include-1.2.3/LICENSE" in tar.getnames() + assert "with_include-1.2.3/README.rst" in tar.getnames() + assert "with_include-1.2.3/extra_dir/__init__.py" in tar.getnames() + assert "with_include-1.2.3/extra_dir/vcs_excluded.txt" in tar.getnames() + assert "with_include-1.2.3/extra_dir/sub_pkg/__init__.py" in tar.getnames() + assert ( + "with_include-1.2.3/extra_dir/sub_pkg/vcs_excluded.txt" + not in tar.getnames() + ) + assert "with_include-1.2.3/my_module.py" in tar.getnames() + assert "with_include-1.2.3/notes.txt" in tar.getnames() + assert "with_include-1.2.3/package_with_include/__init__.py" in tar.getnames() + assert "with_include-1.2.3/tests/__init__.py" in tar.getnames() + assert "with_include-1.2.3/pyproject.toml" in tar.getnames() + assert "with_include-1.2.3/PKG-INFO" in tar.getnames() + assert "with_include-1.2.3/for_wheel_only/__init__.py" not in tar.getnames() + assert "with_include-1.2.3/src/src_package/__init__.py" in tar.getnames() + assert "with_include-1.2.3/etc/from_to/__init__.py" in tar.getnames() + assert len(tar.getnames()) == len(set(tar.getnames())) + + bdist = fixture / "dist" / "with_include-1.2.3-py3-none-any.whl" + assert bdist.exists() + + with zipfile.ZipFile(bdist) as zipf: + assert "with_include-1.2.3.dist-info/LICENSE" in zipf.namelist() + assert "extra_dir/__init__.py" in zipf.namelist() + assert "extra_dir/vcs_excluded.txt" in zipf.namelist() + assert "extra_dir/sub_pkg/__init__.py" in zipf.namelist() + assert "extra_dir/sub_pkg/vcs_excluded.txt" not in zipf.namelist() + assert "for_wheel_only/__init__.py" in zipf.namelist() + assert "my_module.py" in zipf.namelist() + assert "notes.txt" in zipf.namelist() + assert "package_with_include/__init__.py" in zipf.namelist() + assert "tests/__init__.py" not in zipf.namelist() + assert "src_package/__init__.py" in zipf.namelist() + assert "target_from_to/from_to/__init__.py" in zipf.namelist() + assert "target_module/my_module_to.py" in zipf.namelist() + assert len(zipf.namelist()) == len(set(zipf.namelist())) + + +def test_respect_format_for_explicit_included_files( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("exclude-whl-include-sdist") + poetry = Factory().create_poetry(fixture) SdistBuilder(poetry).build() WheelBuilder(poetry).build() - sdist = module_path / "dist" / "exclude_whl_include_sdist-0.1.0.tar.gz" - + sdist = fixture / "dist" / "exclude_whl_include_sdist-0.1.0.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: - names = tar.getnames() + with tarfile.open(sdist, "r") as tar: assert ( "exclude_whl_include_sdist-0.1.0/exclude_whl_include_sdist/__init__.py" - in names + in tar.getnames() ) assert ( "exclude_whl_include_sdist-0.1.0/exclude_whl_include_sdist/compiled/source.c" - in names + in tar.getnames() ) assert ( "exclude_whl_include_sdist-0.1.0/exclude_whl_include_sdist/compiled/source.h" - in names + in tar.getnames() ) assert ( "exclude_whl_include_sdist-0.1.0/exclude_whl_include_sdist/cython_code.pyx" - in names + in tar.getnames() ) - assert "exclude_whl_include_sdist-0.1.0/pyproject.toml" in names - assert "exclude_whl_include_sdist-0.1.0/PKG-INFO" in names - - whl = module_path / "dist" / "exclude_whl_include_sdist-0.1.0-py3-none-any.whl" + assert "exclude_whl_include_sdist-0.1.0/pyproject.toml" in tar.getnames() + assert "exclude_whl_include_sdist-0.1.0/PKG-INFO" in tar.getnames() - assert whl.exists() + bdist = fixture / "dist" / "exclude_whl_include_sdist-0.1.0-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - names = z.namelist() - assert "exclude_whl_include_sdist/__init__.py" in names - assert "exclude_whl_include_sdist/compiled/source.c" not in names - assert "exclude_whl_include_sdist/compiled/source.h" not in names - assert "exclude_whl_include_sdist/cython_code.pyx" not in names + with zipfile.ZipFile(bdist) as zipf: + assert "exclude_whl_include_sdist/__init__.py" in zipf.namelist() + assert "exclude_whl_include_sdist/compiled/source.c" not in zipf.namelist() + assert "exclude_whl_include_sdist/compiled/source.h" not in zipf.namelist() + assert "exclude_whl_include_sdist/cython_code.pyx" not in zipf.namelist() diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index bd1908450..35b4d8c73 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -3,14 +3,12 @@ import ast import gzip import hashlib -import shutil import tarfile from email.parser import Parser from pathlib import Path from typing import TYPE_CHECKING from typing import Any -from typing import Iterator import pytest @@ -27,26 +25,7 @@ if TYPE_CHECKING: from pytest_mock import MockerFixture -fixtures_dir = Path(__file__).parent / "fixtures" - - -@pytest.fixture(autouse=True) -def setup() -> Iterator[None]: - clear_samples_dist() - - yield - - clear_samples_dist() - - -def clear_samples_dist() -> None: - for dist in fixtures_dir.glob("**/dist"): - if dist.is_dir(): - shutil.rmtree(str(dist)) - - -def project(name: str) -> Path: - return Path(__file__).parent / "fixtures" / name + from tests.types import FixtureFactory def test_convert_dependencies() -> None: @@ -117,8 +96,9 @@ def test_convert_dependencies() -> None: @pytest.mark.filterwarnings("ignore:.* script .* extra:DeprecationWarning") -def test_make_setup() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_make_setup(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) setup = builder.build_setup() @@ -149,11 +129,13 @@ def test_make_setup() -> None: } -def test_make_pkg_info(mocker: MockerFixture) -> None: +def test_make_pkg_info(fixture_factory: FixtureFactory, mocker: MockerFixture) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) + get_metadata_content = mocker.patch( "poetry.core.masonry.builders.builder.Builder.get_metadata_content" ) - poetry = Factory().create_poetry(project("complete")) builder = SdistBuilder(poetry) builder.build_pkg_info() @@ -161,8 +143,9 @@ def test_make_pkg_info(mocker: MockerFixture) -> None: assert get_metadata_content.called -def test_make_pkg_info_any_python() -> None: - poetry = Factory().create_poetry(project("module1")) +def test_make_pkg_info_any_python(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("module1") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) pkg_info = builder.build_pkg_info() @@ -172,8 +155,9 @@ def test_make_pkg_info_any_python() -> None: assert "Requires-Python" not in parsed -def test_find_files_to_add() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_find_files_to_add(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) result = {f.relative_to_source_root() for f in builder.find_files_to_add()} @@ -195,10 +179,11 @@ def test_find_files_to_add() -> None: } -def test_find_files_to_add_with_multiple_readme_files() -> None: - poetry = Factory().create_poetry( - Path(__file__).parent.parent.parent / "fixtures" / "with_readme_files" - ) +def test_find_files_to_add_with_multiple_readme_files( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("with_readme_files", scope=Path("")) + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) result = {f.relative_to_source_root() for f in builder.find_files_to_add()} @@ -211,12 +196,13 @@ def test_find_files_to_add_with_multiple_readme_files() -> None: } -def test_make_pkg_info_multi_constraints_dependency() -> None: - poetry = Factory().create_poetry( - Path(__file__).parent.parent.parent - / "fixtures" - / "project_with_multi_constraints_dependency" +def test_make_pkg_info_multi_constraints_dependency( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory( + "project_with_multi_constraints_dependency", scope=Path("") ) + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) pkg_info = builder.build_pkg_info() @@ -230,14 +216,13 @@ def test_make_pkg_info_multi_constraints_dependency() -> None: ] -def test_find_packages() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_find_packages(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) - base = project("complete") - include = PackageInclude(base, "my_package") - + include = PackageInclude(fixture, "my_package") pkg_dir, packages, pkg_data = builder.find_packages(include) assert pkg_dir is None @@ -253,36 +238,36 @@ def test_find_packages() -> None: "my_package.sub_pkg2": ["data2/*"], } - poetry = Factory().create_poetry(project("source_package")) + fixture = fixture_factory("source_package") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) - base = project("source_package") - include = PackageInclude(base, "package_src", source="src") - + include = PackageInclude(fixture, "package_src", source="src") pkg_dir, packages, pkg_data = builder.find_packages(include) - assert pkg_dir == str(base / "src") + assert pkg_dir == str(fixture / "src") assert packages == ["package_src"] assert pkg_data == {"": ["*"]} -def test_package() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_package(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "complete" / "dist" / "my_package-1.2.3.tar.gz" - + sdist = fixture / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "my_package-1.2.3/LICENSE" in tar.getnames() -def test_sdist_reproducibility() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_sdist_reproducibility(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) hashes = set() @@ -290,8 +275,7 @@ def test_sdist_reproducibility() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "complete" / "dist" / "my_package-1.2.3.tar.gz" - + sdist = fixture / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() hashes.add(hashlib.sha256(sdist.read_bytes()).hexdigest()) @@ -300,13 +284,13 @@ def test_sdist_reproducibility() -> None: @pytest.mark.filterwarnings("ignore:.* script .* extra:DeprecationWarning") -def test_setup_py_context() -> None: - poetry = Factory().create_poetry(project("complete")) +def test_setup_py_context(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) project_setup_py = poetry.pyproject_path.parent / "setup.py" - assert not project_setup_py.exists() try: @@ -314,7 +298,7 @@ def test_setup_py_context() -> None: assert setup.exists() assert project_setup_py == setup - with open(str(setup), "rb") as f: + with open(setup, "rb") as f: # we convert to string and replace line endings here for compatibility data = f.read().decode().replace("\r\n", "\n") assert data == builder.build_setup().decode() @@ -325,64 +309,64 @@ def test_setup_py_context() -> None: project_setup_py.unlink() -def test_module() -> None: - poetry = Factory().create_poetry(project("module1")) +def test_module(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("module1") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "module1" / "dist" / "module1-0.1.tar.gz" - + sdist = fixture / "dist" / "module1-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "module1-0.1/module1.py" in tar.getnames() -def test_prelease() -> None: - poetry = Factory().create_poetry(project("prerelease")) +def test_prerelease(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("prerelease") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "prerelease" / "dist" / "prerelease-0.1b1.tar.gz" - + sdist = fixture / "dist" / "prerelease-0.1b1.tar.gz" assert sdist.exists() -@pytest.mark.parametrize("directory", ["extended", "extended_legacy_config"]) -def test_with_c_extensions(directory: str) -> None: - poetry = Factory().create_poetry(project("extended")) +def test_with_c_extensions(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("extended") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "extended" / "dist" / "extended-0.1.tar.gz" - + sdist = fixture / "dist" / "extended-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "extended-0.1/build.py" in tar.getnames() assert "extended-0.1/extended/extended.c" in tar.getnames() -def test_with_c_extensions_src_layout() -> None: - poetry = Factory().create_poetry(project("src_extended")) +def test_with_c_extensions_src_layout(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("src_extended") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "src_extended" / "dist" / "extended-0.1.tar.gz" - + sdist = fixture / "dist" / "extended-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "extended-0.1/build.py" in tar.getnames() assert "extended-0.1/src/extended/extended.c" in tar.getnames() -def test_with_build_script_in_subdir() -> None: - poetry = Factory().create_poetry(project("build_script_in_subdir")) +def test_with_build_script_in_subdir(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("build_script_in_subdir") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) setup = builder.build_setup() @@ -390,8 +374,9 @@ def test_with_build_script_in_subdir() -> None: ast.parse(setup) -def test_with_src_module_file() -> None: - poetry = Factory().create_poetry(project("source_file")) +def test_with_src_module_file(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_file") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) @@ -407,16 +392,16 @@ def test_with_src_module_file() -> None: builder.build() - sdist = fixtures_dir / "source_file" / "dist" / "module_src-0.1.tar.gz" - + sdist = fixture / "dist" / "module_src-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "module_src-0.1/src/module_src.py" in tar.getnames() -def test_with_src_module_dir() -> None: - poetry = Factory().create_poetry(project("source_package")) +def test_with_src_module_dir(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_package") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) @@ -432,38 +417,29 @@ def test_with_src_module_dir() -> None: builder.build() - sdist = fixtures_dir / "source_package" / "dist" / "package_src-0.1.tar.gz" - + sdist = fixture / "dist" / "package_src-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "package_src-0.1/src/package_src/__init__.py" in tar.getnames() assert "package_src-0.1/src/package_src/module.py" in tar.getnames() -def test_default_with_excluded_data(mocker: MockerFixture) -> None: +def test_default_with_excluded_data( + fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: class MockGit: def get_ignored_files(self, folder: Path | None = None) -> list[str]: # Patch git module to return specific excluded files return [ - ( - ( - Path(__file__).parent - / "fixtures" - / "default_with_excluded_data" - / "my_package" - / "data" - / "sub_data" - / "data2.txt" - ) - .relative_to(project("default_with_excluded_data")) - .as_posix() - ) + "my_package/data/sub_data/data2.txt", ] p = mocker.patch("poetry.core.vcs.get_vcs") p.return_value = MockGit() - poetry = Factory().create_poetry(project("default_with_excluded_data")) + + fixture = fixture_factory("default_with_excluded_data") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) @@ -483,21 +459,17 @@ def get_ignored_files(self, folder: Path | None = None) -> list[str]: builder.build() - sdist = ( - fixtures_dir / "default_with_excluded_data" / "dist" / "my_package-1.2.3.tar.gz" - ) - + sdist = fixture / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: - names = tar.getnames() - assert len(names) == len(set(names)) - assert "my_package-1.2.3/LICENSE" in names - assert "my_package-1.2.3/README.rst" in names - assert "my_package-1.2.3/my_package/__init__.py" in names - assert "my_package-1.2.3/my_package/data/data1.txt" in names - assert "my_package-1.2.3/pyproject.toml" in names - assert "my_package-1.2.3/PKG-INFO" in names + with tarfile.open(sdist, "r") as tar: + assert "my_package-1.2.3/LICENSE" in tar.getnames() + assert "my_package-1.2.3/README.rst" in tar.getnames() + assert "my_package-1.2.3/my_package/__init__.py" in tar.getnames() + assert "my_package-1.2.3/my_package/data/data1.txt" in tar.getnames() + assert "my_package-1.2.3/pyproject.toml" in tar.getnames() + assert "my_package-1.2.3/PKG-INFO" in tar.getnames() + assert len(tar.getnames()) == len(set(tar.getnames())) # all last modified times should be set to a valid timestamp for tarinfo in tar.getmembers(): if tarinfo.name in [ @@ -510,40 +482,51 @@ def get_ignored_files(self, folder: Path | None = None) -> list[str]: assert tarinfo.mtime > 0 -def test_src_excluded_nested_data() -> None: - module_path = fixtures_dir / "exclude_nested_data_toml" - poetry = Factory().create_poetry(module_path) +def test_src_excluded_nested_data(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("exclude_nested_data_toml") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = module_path / "dist" / "my_package-1.2.3.tar.gz" - + sdist = fixture / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: - names = tar.getnames() - assert len(names) == len(set(names)) - assert "my_package-1.2.3/LICENSE" in names - assert "my_package-1.2.3/README.rst" in names - assert "my_package-1.2.3/pyproject.toml" in names - assert "my_package-1.2.3/PKG-INFO" in names - assert "my_package-1.2.3/my_package/__init__.py" in names - assert "my_package-1.2.3/my_package/data/sub_data/data2.txt" not in names - assert "my_package-1.2.3/my_package/data/sub_data/data3.txt" not in names - assert "my_package-1.2.3/my_package/data/data1.txt" not in names - assert "my_package-1.2.3/my_package/data/data2.txt" in names - assert "my_package-1.2.3/my_package/puplic/publicdata.txt" in names - assert "my_package-1.2.3/my_package/public/item1/itemdata1.txt" not in names + with tarfile.open(sdist, "r") as tar: + assert "my_package-1.2.3/LICENSE" in tar.getnames() + assert "my_package-1.2.3/README.rst" in tar.getnames() + assert "my_package-1.2.3/pyproject.toml" in tar.getnames() + assert "my_package-1.2.3/PKG-INFO" in tar.getnames() + assert "my_package-1.2.3/my_package/__init__.py" in tar.getnames() + assert ( + "my_package-1.2.3/my_package/data/sub_data/data2.txt" not in tar.getnames() + ) + assert ( + "my_package-1.2.3/my_package/data/sub_data/data3.txt" not in tar.getnames() + ) + assert "my_package-1.2.3/my_package/data/data1.txt" not in tar.getnames() + assert "my_package-1.2.3/my_package/data/data2.txt" in tar.getnames() + assert "my_package-1.2.3/my_package/public/publicdata.txt" in tar.getnames() + assert ( + "my_package-1.2.3/my_package/public/item1/itemdata1.txt" + not in tar.getnames() + ) assert ( "my_package-1.2.3/my_package/public/item1/subitem/subitemdata.txt" - not in names + not in tar.getnames() + ) + assert ( + "my_package-1.2.3/my_package/public/item2/itemdata2.txt" + not in tar.getnames() ) - assert "my_package-1.2.3/my_package/public/item2/itemdata2.txt" not in names + assert len(tar.getnames()) == len(set(tar.getnames())) -def test_proper_python_requires_if_two_digits_precision_version_specified() -> None: - poetry = Factory().create_poetry(project("simple_version")) +def test_proper_python_requires_if_two_digits_precision_version_specified( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("simple_version") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) pkg_info = builder.build_pkg_info() @@ -553,8 +536,11 @@ def test_proper_python_requires_if_two_digits_precision_version_specified() -> N assert parsed["Requires-Python"] == ">=3.6,<3.7" -def test_proper_python_requires_if_three_digits_precision_version_specified() -> None: - poetry = Factory().create_poetry(project("single_python")) +def test_proper_python_requires_if_three_digits_precision_version_specified( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("single_python") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) pkg_info = builder.build_pkg_info() @@ -564,47 +550,52 @@ def test_proper_python_requires_if_three_digits_precision_version_specified() -> assert parsed["Requires-Python"] == "==2.7.15" -def test_includes() -> None: - poetry = Factory().create_poetry(project("with-include")) +def test_includes(fixture_factory: FixtureFactory, mocker: MockerFixture) -> None: + class MockGit: + def get_ignored_files(self, folder: Path | None = None) -> list[str]: + # Patch git module to return specific excluded files + return [ + "extra_dir/vcs_excluded.txt", + "extra_dir/sub_pkg/vcs_excluded.txt", + ] - builder = SdistBuilder(poetry) + p = mocker.patch("poetry.core.vcs.get_vcs") + p.return_value = MockGit() - builder.build() + fixture = fixture_factory("with-include") + poetry = Factory().create_poetry(fixture) - sdist = fixtures_dir / "with-include" / "dist" / "with_include-1.2.3.tar.gz" + builder = SdistBuilder(poetry) + builder.build() + sdist = fixture / "dist" / "with_include-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "with_include-1.2.3/extra_dir/vcs_excluded.txt" in tar.getnames() assert "with_include-1.2.3/notes.txt" in tar.getnames() -def test_includes_with_inline_table() -> None: - poetry = Factory().create_poetry(project("with_include_inline_table")) +def test_includes_with_inline_table(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("with_include_inline_table") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) - builder.build() - sdist = ( - fixtures_dir - / "with_include_inline_table" - / "dist" - / "with_include-1.2.3.tar.gz" - ) - + sdist = fixture / "dist" / "with_include-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert "with_include-1.2.3/both.txt" in tar.getnames() assert "with_include-1.2.3/wheel_only.txt" not in tar.getnames() assert "with_include-1.2.3/tests/__init__.py" in tar.getnames() assert "with_include-1.2.3/tests/test_foo/test.py" in tar.getnames() -def test_excluded_subpackage() -> None: - poetry = Factory().create_poetry(project("excluded_subpackage")) +def test_excluded_subpackage(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("excluded_subpackage") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) setup = builder.build_setup() @@ -618,36 +609,34 @@ def test_excluded_subpackage() -> None: assert ns["packages"] == ["example"] -def test_sdist_package_pep_561_stub_only() -> None: - root = fixtures_dir / "pep_561_stub_only" - poetry = Factory().create_poetry(root) +def test_sdist_package_pep_561_stub_only(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("pep_561_stub_only") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = root / "dist" / "pep_561_stubs-0.1.tar.gz" - + sdist = fixture / "dist" / "pep_561_stubs-0.1.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: names = tar.getnames() assert "pep_561_stubs-0.1/pkg-stubs/__init__.pyi" in names assert "pep_561_stubs-0.1/pkg-stubs/module.pyi" in names assert "pep_561_stubs-0.1/pkg-stubs/subpkg/__init__.pyi" in names -def test_sdist_disable_setup_py() -> None: - module_path = fixtures_dir / "disable_setup_py" - poetry = Factory().create_poetry(module_path) +def test_sdist_disable_setup_py(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("disable_setup_py") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = module_path / "dist" / "my_package-1.2.3.tar.gz" - + sdist = fixture / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() - with tarfile.open(str(sdist), "r") as tar: + with tarfile.open(sdist, "r") as tar: assert set(tar.getnames()) == { "my_package-1.2.3/README.rst", "my_package-1.2.3/pyproject.toml", @@ -656,24 +645,24 @@ def test_sdist_disable_setup_py() -> None: } -def test_sdist_mtime_zero() -> None: - poetry = Factory().create_poetry(project("module1")) +def test_sdist_mtime_zero(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("module1") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "module1" / "dist" / "module1-0.1.tar.gz" - + sdist = fixture / "dist" / "module1-0.1.tar.gz" assert sdist.exists() - with gzip.open(str(sdist), "rb") as gz: - gz.read(100) - assert gz.mtime == 0 + with gzip.open(sdist, "rb") as tar: + tar.read(100) + assert tar.mtime == 0 -def test_split_source() -> None: - root = fixtures_dir / "split_source" - poetry = Factory().create_poetry(root) +def test_split_source(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("split_source") + poetry = Factory().create_poetry(fixture) builder = SdistBuilder(poetry) diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py index a7f6c890e..9329664a3 100644 --- a/tests/masonry/builders/test_wheel.py +++ b/tests/masonry/builders/test_wheel.py @@ -3,400 +3,390 @@ import importlib.machinery import os import re -import shutil import zipfile -from pathlib import Path from typing import TYPE_CHECKING from typing import Any -from typing import Iterator from typing import TextIO import pytest from poetry.core.factory import Factory from poetry.core.masonry.builders.wheel import WheelBuilder -from tests.masonry.builders.test_sdist import project if TYPE_CHECKING: + from pathlib import Path + from _pytest.monkeypatch import MonkeyPatch from pytest_mock import MockerFixture -fixtures_dir = Path(__file__).parent / "fixtures" + from tests.types import FixtureFactory WHEEL_TAG_REGEX = "[cp]p[23]_?\\d+-(?:cp[23]_?\\d+m?u?|pypy[23]_?\\d+_pp\\d+)-.+" - shared_lib_extensions = importlib.machinery.EXTENSION_SUFFIXES -@pytest.fixture(autouse=True) -def setup() -> Iterator[None]: - clear_samples_dist() - clear_samples_build() - - yield - - clear_samples_dist() - clear_samples_build() - - -def clear_samples_dist() -> None: - for dist in fixtures_dir.glob("**/dist"): - if dist.is_dir(): - shutil.rmtree(str(dist)) - +def test_wheel_module(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("module1") + poetry = Factory().create_poetry(fixture) -def clear_samples_build() -> None: - for build in fixtures_dir.glob("**/build"): - if build.is_dir(): - shutil.rmtree(str(build)) - for suffix in shared_lib_extensions: - for shared_lib in fixtures_dir.glob(f"**/*{suffix}"): - shared_lib.unlink() - - -def test_wheel_module() -> None: - module_path = fixtures_dir / "module1" - WheelBuilder.make(Factory().create_poetry(module_path)) - - whl = module_path / "dist" / "module1-0.1-py2.py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() + bdist = fixture / "dist" / "module1-0.1-py2.py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "module1.py" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "module1.py" in zipf.namelist() @pytest.mark.filterwarnings("ignore:.* script .* extra:DeprecationWarning") -def test_wheel_package() -> None: - module_path = fixtures_dir / "complete" - WheelBuilder.make(Factory().create_poetry(module_path)) +def test_wheel_package(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) + + WheelBuilder.make(poetry) - whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl" + fixture = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert fixture.exists() - assert whl.exists() + with zipfile.ZipFile(fixture) as zipf: + assert "my_package/sub_pkg1/__init__.py" in zipf.namelist() - with zipfile.ZipFile(str(whl)) as z: - assert "my_package/sub_pkg1/__init__.py" in z.namelist() +def test_wheel_prerelease(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("prerelease") + poetry = Factory().create_poetry(fixture) -def test_wheel_prerelease() -> None: - module_path = fixtures_dir / "prerelease" - WheelBuilder.make(Factory().create_poetry(module_path)) + WheelBuilder.make(poetry) - whl = module_path / "dist" / "prerelease-0.1b1-py2.py3-none-any.whl" + bdist = fixture / "dist" / "prerelease-0.1b1-py2.py3-none-any.whl" + assert bdist.exists() - assert whl.exists() +def test_wheel_epoch(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("epoch") + poetry = Factory().create_poetry(fixture) -def test_wheel_epoch() -> None: - module_path = fixtures_dir / "epoch" - WheelBuilder.make(Factory().create_poetry(module_path)) + WheelBuilder.make(poetry) - whl = module_path / "dist" / "epoch-1!2.0-py2.py3-none-any.whl" + bdist = fixture / "dist" / "epoch-1!2.0-py2.py3-none-any.whl" + assert bdist.exists() - assert whl.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "epoch-1!2.0.dist-info/METADATA" in zipf.namelist() - with zipfile.ZipFile(str(whl)) as z: - assert "epoch-1!2.0.dist-info/METADATA" in z.namelist() +def test_wheel_excluded_data(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("default_with_excluded_data_toml") + poetry = Factory().create_poetry(fixture) -def test_wheel_excluded_data() -> None: - module_path = fixtures_dir / "default_with_excluded_data_toml" - WheelBuilder.make(Factory().create_poetry(module_path)) + WheelBuilder.make(poetry) - whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl" + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() - assert whl.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "my_package/__init__.py" in zipf.namelist() + assert "my_package/data/sub_data/data2.txt" in zipf.namelist() + assert "my_package/data/sub_data/data3.txt" in zipf.namelist() + assert "my_package/data/data1.txt" not in zipf.namelist() - with zipfile.ZipFile(str(whl)) as z: - assert "my_package/__init__.py" in z.namelist() - assert "my_package/data/sub_data/data2.txt" in z.namelist() - assert "my_package/data/sub_data/data3.txt" in z.namelist() - assert "my_package/data/data1.txt" not in z.namelist() +def test_wheel_excluded_nested_data(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("exclude_nested_data_toml") + poetry = Factory().create_poetry(fixture) -def test_wheel_excluded_nested_data() -> None: - module_path = fixtures_dir / "exclude_nested_data_toml" - poetry = Factory().create_poetry(module_path) WheelBuilder.make(poetry) - whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl" + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() - assert whl.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "my_package/__init__.py" in zipf.namelist() + assert "my_package/data/sub_data/data2.txt" not in zipf.namelist() + assert "my_package/data/sub_data/data3.txt" not in zipf.namelist() + assert "my_package/data/data1.txt" not in zipf.namelist() + assert "my_package/data/data2.txt" in zipf.namelist() + assert "my_package/public/publicdata.txt" in zipf.namelist() + assert "my_package/public/item1/itemdata1.txt" not in zipf.namelist() + assert "my_package/public/item1/subitem/subitemdata.txt" not in zipf.namelist() + assert "my_package/public/item2/itemdata2.txt" not in zipf.namelist() - with zipfile.ZipFile(str(whl)) as z: - assert "my_package/__init__.py" in z.namelist() - assert "my_package/data/sub_data/data2.txt" not in z.namelist() - assert "my_package/data/sub_data/data3.txt" not in z.namelist() - assert "my_package/data/data1.txt" not in z.namelist() - assert "my_package/data/data2.txt" in z.namelist() - assert "my_package/puplic/publicdata.txt" in z.namelist() - assert "my_package/public/item1/itemdata1.txt" not in z.namelist() - assert "my_package/public/item1/subitem/subitemdata.txt" not in z.namelist() - assert "my_package/public/item2/itemdata2.txt" not in z.namelist() +def test_include_excluded_code(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("include_excluded_code") + poetry = Factory().create_poetry(fixture) -def test_include_excluded_code() -> None: - module_path = fixtures_dir / "include_excluded_code" - poetry = Factory().create_poetry(module_path) wb = WheelBuilder(poetry) wb.build() - whl = module_path / "dist" / wb.wheel_filename - assert whl.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "my_package/__init__.py" in z.namelist() - assert "my_package/generated.py" in z.namelist() - assert "lib/my_package/generated.py" not in z.namelist() + bdist = fixture / "dist" / wb.wheel_filename + assert bdist.exists() + + with zipfile.ZipFile(bdist) as zipf: + assert "my_package/__init__.py" in zipf.namelist() + assert "my_package/generated.py" in zipf.namelist() + assert "lib/my_package/generated.py" not in zipf.namelist() -def test_wheel_localversionlabel() -> None: - module_path = fixtures_dir / "localversionlabel" - project = Factory().create_poetry(module_path) +def test_wheel_localversionlabel(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("localversionlabel") + project = Factory().create_poetry(fixture) + WheelBuilder.make(project) - local_version_string = "localversionlabel-0.1b1+gitbranch.buildno.1" - whl = module_path / "dist" / (local_version_string + "-py2.py3-none-any.whl") - assert whl.exists() + local_version_string = "localversionlabel-0.1b1+gitbranch.buildno.1" - with zipfile.ZipFile(str(whl)) as z: - assert local_version_string + ".dist-info/METADATA" in z.namelist() + bdist = fixture / "dist" / (local_version_string + "-py2.py3-none-any.whl") + assert bdist.exists() + with zipfile.ZipFile(bdist) as zipf: + assert local_version_string + ".dist-info/METADATA" in zipf.namelist() -def test_wheel_package_src() -> None: - module_path = fixtures_dir / "source_package" - WheelBuilder.make(Factory().create_poetry(module_path)) - whl = module_path / "dist" / "package_src-0.1-py2.py3-none-any.whl" +def test_wheel_package_src(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_package") + poetry = Factory().create_poetry(fixture) - assert whl.exists() + WheelBuilder.make(poetry) - with zipfile.ZipFile(str(whl)) as z: - assert "package_src/__init__.py" in z.namelist() - assert "package_src/module.py" in z.namelist() + bdist = fixture / "dist" / "package_src-0.1-py2.py3-none-any.whl" + assert bdist.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "package_src/__init__.py" in zipf.namelist() + assert "package_src/module.py" in zipf.namelist() -def test_wheel_module_src() -> None: - module_path = fixtures_dir / "source_file" - WheelBuilder.make(Factory().create_poetry(module_path)) - whl = module_path / "dist" / "module_src-0.1-py2.py3-none-any.whl" +def test_wheel_module_src(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("source_file") + poetry = Factory().create_poetry(fixture) - assert whl.exists() + WheelBuilder.make(poetry) - with zipfile.ZipFile(str(whl)) as z: - assert "module_src.py" in z.namelist() + bdist = fixture / "dist" / "module_src-0.1-py2.py3-none-any.whl" + assert bdist.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "module_src.py" in zipf.namelist() -def test_wheel_build_script_creates_package() -> None: - module_path = fixtures_dir / "build_script_creates_package" - WheelBuilder.make(Factory().create_poetry(module_path)) - # Currently, if a build.py script is used, - # poetry just assumes the most specific tags - whl = next((module_path / "dist").glob("my_package-0.1-*.whl")) +def test_wheel_build_script_creates_package(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("build_script_creates_package") + poetry = Factory().create_poetry(fixture) - assert whl.exists() + WheelBuilder.make(poetry) - with zipfile.ZipFile(str(whl)) as z: - assert "my_package/__init__.py" in z.namelist() - assert "my_package/foo.py" in z.namelist() + # Currently, if a build.py script is used, + # poetry just assumes the most specific tags + bdist = next((fixture / "dist").glob("my_package-0.1-*.whl")) + assert bdist.exists() - shutil.rmtree(module_path / "my_package") + with zipfile.ZipFile(bdist) as zipf: + assert "my_package/__init__.py" in zipf.namelist() + assert "my_package/foo.py" in zipf.namelist() @pytest.mark.filterwarnings("ignore:.* script .* extra:DeprecationWarning") -def test_dist_info_file_permissions() -> None: - module_path = fixtures_dir / "complete" - WheelBuilder.make(Factory().create_poetry(module_path)) +def test_dist_info_file_permissions(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("complete") + poetry = Factory().create_poetry(fixture) + + WheelBuilder.make(poetry) - whl = module_path / "dist" / "my_package-1.2.3-py3-none-any.whl" + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: + with zipfile.ZipFile(bdist) as zipf: assert ( - z.getinfo("my_package-1.2.3.dist-info/WHEEL").external_attr & 0x1FF0000 + zipf.getinfo("my_package-1.2.3.dist-info/WHEEL").external_attr & 0x1FF0000 == 0o644 << 16 ) assert ( - z.getinfo("my_package-1.2.3.dist-info/METADATA").external_attr & 0x1FF0000 + zipf.getinfo("my_package-1.2.3.dist-info/METADATA").external_attr + & 0x1FF0000 == 0o644 << 16 ) assert ( - z.getinfo("my_package-1.2.3.dist-info/RECORD").external_attr & 0x1FF0000 + zipf.getinfo("my_package-1.2.3.dist-info/RECORD").external_attr & 0x1FF0000 == 0o644 << 16 ) assert ( - z.getinfo("my_package-1.2.3.dist-info/entry_points.txt").external_attr + zipf.getinfo("my_package-1.2.3.dist-info/entry_points.txt").external_attr & 0x1FF0000 == 0o644 << 16 ) -def test_wheel_includes_inline_table() -> None: - module_path = fixtures_dir / "with_include_inline_table" - WheelBuilder.make(Factory().create_poetry(module_path)) +def test_wheel_includes_inline_table(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("with_include_inline_table") + poetry = Factory().create_poetry(fixture) - whl = module_path / "dist" / "with_include-1.2.3-py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() + bdist = fixture / "dist" / "with_include-1.2.3-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "both.txt" in z.namelist() - assert "wheel_only.txt" in z.namelist() - assert "notes.txt" not in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "both.txt" in zipf.namelist() + assert "wheel_only.txt" in zipf.namelist() + assert "notes.txt" not in zipf.namelist() @pytest.mark.parametrize( - "package", + "fixture_name", ["pep_561_stub_only", "pep_561_stub_only_partial", "pep_561_stub_only_src"], ) -def test_wheel_package_pep_561_stub_only(package: str) -> None: - root = fixtures_dir / package - WheelBuilder.make(Factory().create_poetry(root)) +def test_wheel_package_pep_561_stub_only( + fixture_name: str, fixture_factory: FixtureFactory +) -> None: + fixture = fixture_factory(fixture_name) + poetry = Factory().create_poetry(fixture) - whl = root / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() + bdist = fixture / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "pkg-stubs/__init__.pyi" in z.namelist() - assert "pkg-stubs/module.pyi" in z.namelist() - assert "pkg-stubs/subpkg/__init__.pyi" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "pkg-stubs/__init__.pyi" in zipf.namelist() + assert "pkg-stubs/module.pyi" in zipf.namelist() + assert "pkg-stubs/subpkg/__init__.pyi" in zipf.namelist() -def test_wheel_package_pep_561_stub_only_partial_namespace() -> None: - root = fixtures_dir / "pep_561_stub_only_partial_namespace" - WheelBuilder.make(Factory().create_poetry(root)) +def test_wheel_package_pep_561_stub_only_partial_namespace( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("pep_561_stub_only_partial_namespace") + poetry = Factory().create_poetry(fixture) - whl = root / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() + bdist = fixture / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "pkg-stubs/module.pyi" in z.namelist() - assert "pkg-stubs/subpkg/__init__.pyi" in z.namelist() - assert "pkg-stubs/subpkg/py.typed" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "pkg-stubs/module.pyi" in zipf.namelist() + assert "pkg-stubs/subpkg/__init__.pyi" in zipf.namelist() + assert "pkg-stubs/subpkg/py.typed" in zipf.namelist() -def test_wheel_package_pep_561_stub_only_includes_typed_marker() -> None: - root = fixtures_dir / "pep_561_stub_only_partial" - WheelBuilder.make(Factory().create_poetry(root)) +def test_wheel_package_pep_561_stub_only_includes_typed_marker( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("pep_561_stub_only_partial") + poetry = Factory().create_poetry(fixture) - whl = root / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() + bdist = fixture / "dist" / "pep_561_stubs-0.1-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "pkg-stubs/py.typed" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "pkg-stubs/py.typed" in zipf.namelist() -def test_wheel_includes_licenses_in_correct_paths() -> None: - root = fixtures_dir / "licenses_and_copying" - WheelBuilder.make(Factory().create_poetry(root)) +def test_wheel_includes_licenses_in_correct_paths( + fixture_factory: FixtureFactory, +) -> None: + fixture = fixture_factory("licenses_and_copying") + poetry = Factory().create_poetry(fixture) - whl = root / "dist" / "my_package-1.2.3-py3-none-any.whl" + WheelBuilder.make(poetry) - assert whl.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "my_package-1.2.3.dist-info/COPYING" in z.namelist() - assert "my_package-1.2.3.dist-info/COPYING.txt" in z.namelist() - assert "my_package-1.2.3.dist-info/LICENSE" in z.namelist() - assert "my_package-1.2.3.dist-info/LICENSE.md" in z.namelist() - assert "my_package-1.2.3.dist-info/LICENSES/CUSTOM-LICENSE" in z.namelist() - assert "my_package-1.2.3.dist-info/LICENSES/BSD-3.md" in z.namelist() - assert "my_package-1.2.3.dist-info/LICENSES/MIT.txt" in z.namelist() + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "my_package-1.2.3.dist-info/COPYING" in zipf.namelist() + assert "my_package-1.2.3.dist-info/COPYING.txt" in zipf.namelist() + assert "my_package-1.2.3.dist-info/LICENSE" in zipf.namelist() + assert "my_package-1.2.3.dist-info/LICENSE.md" in zipf.namelist() + assert "my_package-1.2.3.dist-info/LICENSES/CUSTOM-LICENSE" in zipf.namelist() + assert "my_package-1.2.3.dist-info/LICENSES/BSD-3.md" in zipf.namelist() + assert "my_package-1.2.3.dist-info/LICENSES/MIT.txt" in zipf.namelist() -def test_wheel_with_file_with_comma() -> None: - root = fixtures_dir / "comma_file" - WheelBuilder.make(Factory().create_poetry(root)) - whl = root / "dist" / "comma_file-1.2.3-py3-none-any.whl" +def test_wheel_with_file_with_comma(fixture_factory: FixtureFactory) -> None: + fixture = fixture_factory("comma_file") + poetry = Factory().create_poetry(fixture) - assert whl.exists() + WheelBuilder.make(poetry) + + bdist = fixture / "dist" / "comma_file-1.2.3-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - records = z.read("comma_file-1.2.3.dist-info/RECORD") + with zipfile.ZipFile(bdist) as zipf: + records = zipf.read("comma_file-1.2.3.dist-info/RECORD") assert '\n"comma_file/a,b.py"' in records.decode() -def test_default_src_with_excluded_data(mocker: MockerFixture) -> None: +def test_default_src_with_excluded_data( + fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: class MockGit: def get_ignored_files(self, folder: Path | None = None) -> list[str]: # Patch git module to return specific excluded files return [ - ( - ( - Path(__file__).parent - / "fixtures" - / "default_src_with_excluded_data" - / "src" - / "my_package" - / "data" - / "sub_data" - / "data2.txt" - ) - .relative_to(project("default_src_with_excluded_data")) - .as_posix() - ) + "src/my_package/data/sub_data/data2.txt", ] p = mocker.patch("poetry.core.vcs.get_vcs") p.return_value = MockGit() - poetry = Factory().create_poetry(project("default_src_with_excluded_data")) + + fixture = fixture_factory("default_src_with_excluded_data") + poetry = Factory().create_poetry(fixture) builder = WheelBuilder(poetry) builder.build() - whl = ( - fixtures_dir - / "default_src_with_excluded_data" - / "dist" - / "my_package-1.2.3-py3-none-any.whl" - ) - - assert whl.exists() + bdist = fixture / "dist" / "my_package-1.2.3-py3-none-any.whl" + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - names = z.namelist() - assert "my_package/__init__.py" in names - assert "my_package/data/data1.txt" in names - assert "my_package/data/sub_data/data2.txt" not in names - assert "my_package/data/sub_data/data3.txt" in names + with zipfile.ZipFile(bdist) as zipf: + assert "my_package/__init__.py" in zipf.namelist() + assert "my_package/data/data1.txt" in zipf.namelist() + assert "my_package/data/sub_data/data2.txt" not in zipf.namelist() + assert "my_package/data/sub_data/data3.txt" in zipf.namelist() -def test_wheel_file_is_closed(monkeypatch: MonkeyPatch) -> None: +def test_wheel_file_is_closed( + fixture_factory: FixtureFactory, monkeypatch: MonkeyPatch +) -> None: """Confirm that wheel zip files are explicitly closed.""" - - # Using a list is a hack for Python 2.7 compatibility. - fd_file: list[TextIO | None] = [None] - + fd_file: TextIO | None = None real_fdopen = os.fdopen def capturing_fdopen(*args: Any, **kwargs: Any) -> TextIO | None: - fd_file[0] = real_fdopen(*args, **kwargs) - return fd_file[0] + nonlocal fd_file + fd_file = real_fdopen(*args, **kwargs) + return fd_file + + monkeypatch.setattr("os.fdopen", capturing_fdopen) - monkeypatch.setattr(os, "fdopen", capturing_fdopen) + fixture = fixture_factory("module1") + poetry = Factory().create_poetry(fixture) - module_path = fixtures_dir / "module1" - WheelBuilder.make(Factory().create_poetry(module_path)) + WheelBuilder.make(poetry) - assert fd_file[0] is not None - assert fd_file[0].closed + assert fd_file is not None + assert fd_file.closed @pytest.mark.parametrize("in_venv_build", [True, False]) -def test_tag(in_venv_build: bool, mocker: MockerFixture) -> None: - """Tests that tag returns a valid tag if a build script is used, +def test_tag( + in_venv_build: bool, fixture_factory: FixtureFactory, mocker: MockerFixture +) -> None: + """ + Tests that tag returns a valid tag if a build script is used, no matter if poetry-core lives inside the build environment or not. """ - root = fixtures_dir / "extended" - builder = WheelBuilder(Factory().create_poetry(root)) + fixture = fixture_factory("extended") + poetry = Factory().create_poetry(fixture) + builder = WheelBuilder(poetry) get_sys_tags_spy = mocker.spy(builder, "_get_sys_tags") if not in_venv_build: @@ -409,62 +399,68 @@ def test_tag(in_venv_build: bool, mocker: MockerFixture) -> None: get_sys_tags_spy.assert_called() -def test_extended_editable_wheel_build() -> None: - """Tests that an editable wheel made from a project with extensions includes +def test_extended_editable_wheel_build(fixture_factory: FixtureFactory) -> None: + """ + Tests that an editable wheel made from a project with extensions includes the .pth, but does not include the built package itself. """ - root = fixtures_dir / "extended" - WheelBuilder.make_in(Factory().create_poetry(root), editable=True) + fixture = fixture_factory("extended") + poetry = Factory().create_poetry(fixture) + + WheelBuilder.make_in(poetry, editable=True) - whl = next((root / "dist").glob("extended-0.1-*.whl")) + bdist = next((fixture / "dist").glob("extended-0.1-*.whl")) - assert whl.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "extended.pth" in z.namelist() + assert bdist.exists() + with zipfile.ZipFile(bdist) as zipf: + assert "extended.pth" in zipf.namelist() # Ensure the directory "extended/" does not exist in the whl - assert all(not n.startswith("extended/") for n in z.namelist()) + assert all(not n.startswith("extended/") for n in zipf.namelist()) -def test_extended_editable_build_inplace() -> None: - """Tests that a project with extensions builds the extension modules in-place +def test_extended_editable_build_inplace(fixture_factory: FixtureFactory) -> None: + """ + Tests that a project with extensions builds the extension modules in-place when ran for an editable install. """ - root = fixtures_dir / "extended" - WheelBuilder.make_in(Factory().create_poetry(root), editable=True) + fixture = fixture_factory("extended") + poetry = Factory().create_poetry(fixture) + + WheelBuilder.make_in(poetry, editable=True) # Check that an extension with any of the allowed extensions was built in-place assert any( - (root / "extended" / f"extended{ext}").exists() for ext in shared_lib_extensions + (fixture / "extended" / f"extended{ext}").exists() + for ext in shared_lib_extensions ) -def test_build_py_only_included() -> None: - """Tests that a build.py that only defined the command build_py (which generates a +def test_build_py_only_included(fixture_factory: FixtureFactory) -> None: + """ + Tests that a build.py that only defined the command build_py (which generates a lib folder) will have its artifacts included. """ - root = fixtures_dir / "build_with_build_py_only" - WheelBuilder.make(Factory().create_poetry(root)) + fixture = fixture_factory("build_with_build_py_only") + poetry = Factory().create_poetry(fixture) - whl = next((root / "dist").glob("build_with_build_py_only-0.1-*.whl")) + WheelBuilder.make(poetry) - assert whl.exists() + bdist = next((fixture / "dist").glob("build_with_build_py_only-0.1-*.whl")) + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "build_with_build_py_only/generated/file.py" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "build_with_build_py_only/generated/file.py" in zipf.namelist() -def test_generated_script_file(tmp_path: Path) -> None: +def test_generated_script_file(fixture_factory: FixtureFactory) -> None: """Tests that a file that is generated by build.py can be used as script.""" - root = fixtures_dir / "generated_script_file" - # test only works on a fresh root without already generated script file: - tmp_root = tmp_path / "generated_script_file" - shutil.copytree(root, tmp_root) - - WheelBuilder.make(Factory().create_poetry(tmp_root)) + fixture = fixture_factory("generated_script_file") + poetry = Factory().create_poetry(fixture) - whl = next((tmp_root / "dist").glob("generated_script_file-0.1-*.whl")) + WheelBuilder.make(poetry) - assert whl.exists() + bdist = next((fixture / "dist").glob("generated_script_file-0.1-*.whl")) + assert bdist.exists() - with zipfile.ZipFile(str(whl)) as z: - assert "generated_script_file-0.1.data/scripts/script.sh" in z.namelist() + with zipfile.ZipFile(bdist) as zipf: + assert "generated_script_file-0.1.data/scripts/script.sh" in zipf.namelist() From 2764247de389a0c9989df98ee4556f1233cb2164 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Fri, 29 Mar 2024 22:41:36 -0600 Subject: [PATCH 03/13] github: remove issue template Issues are disabled on this repo; so this file does nothing. --- .github/ISSUE_TEMPLATE/config.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 2d33a8d19..000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,12 +0,0 @@ -# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser -blank_issues_enabled: false -contact_links: -- name: '✏️ Poetry Issue Tracker' - url: https://github.com/python-poetry/poetry/issues/new/choose - about: | - Submit your issues to the Poetry issue tracker. Bug reports and feature requests - will be tracked there. -- name: '💬 Discord Server' - url: https://discordapp.com/invite/awxPgve - about: | - Chat with the community, ask questions and learn about best practices. From b7e1940917dc3d7d61e67c473af100f194296ac4 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 14:10:27 -0600 Subject: [PATCH 04/13] gitignore: cleanup and simplify --- .gitignore | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index c2d2a7209..dbed70b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,41 +1,17 @@ -*.pyc +# Poetry/virtual environments +/poetry.toml +.venv -# Packages -*.egg -!/tests/**/*.egg -/*.egg-info -/tests/fixtures/**/*.egg-info +# distfiles /dist/* -build -_build -.cache -*.so - -# Installer logs -pip-log.txt -# Unit test / coverage reports +# bytecode/cache +*.pyc .coverage -.tox .pytest_cache +.mypy_cache -.DS_Store -.idea/* +# local tooling/IDEs .python-version +.idea/* .vscode/* - -/test.py -/test_*.* - -/setup.cfg -MANIFEST.in -/setup.py -/docs/site/* -/tests/fixtures/simple_project/setup.py -/tests/fixtures/project_with_extras/setup.py -.mypy_cache - -.venv -/releases/* -pip-wheel-metadata -/poetry.toml From 79994ca8707800081bcbf0c435b4d5bf4a452295 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sat, 30 Mar 2024 00:38:27 -0600 Subject: [PATCH 05/13] pyproject: sync ruff config from poetry --- pyproject.toml | 53 ++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 02b0735ff..34bd7a86f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,13 @@ virtualenv = ">=20.21" mypy = ">=1.0" types-setuptools = ">=57.4.14" + +[build-system] +requires = [] +build-backend = "poetry.core.masonry.api" +backend-path = ["src"] + + [tool.ruff] extend-exclude = [ "src/poetry/core/_vendor/*", @@ -54,27 +61,31 @@ src = ["src"] target-version = "py38" [tool.ruff.lint] -unfixable = [ - "ERA", # do not autoremove commented out code -] extend-select = [ - "B", # flake8-bugbear + "B", # flake8-bugbear "C4", # flake8-comprehensions - "ERA", # flake8-eradicate/eradicate - "PIE", # flake8-pie - "SIM", # flake8-simplify - "TID", # flake8-tidy-imports - "TCH", # flake8-type-checking - "N", # pep8-naming - "RUF", # ruff checks + "ERA", # flake8-eradicate/eradicate + "I", # isort + "N", # pep8-naming + "PIE", # flake8-pie + "PGH", # pygrep + "RUF", # ruff checks + "SIM", # flake8-simplify + "T20", # flake8-print + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports "UP", # pyupgrade - "I", # isort - "PGH", # pygrep ] ignore = [ - "B904", # use 'raise ... from err' - "B905", # use explicit 'strict=' parameter with 'zip()' - "N818" # Exception name should be named with an Error suffix + "B904", # use 'raise ... from err' + "B905", # use explicit 'strict=' parameter with 'zip()' + "N818", # Exception name should be named with an Error suffix +] +extend-safe-fixes = [ + "TCH", # move import from and to TYPE_CHECKING blocks +] +unfixable = [ + "ERA", # do not autoremove commented out code ] [tool.ruff.lint.flake8-tidy-imports] @@ -88,10 +99,6 @@ known-first-party = ["poetry.core"] known-third-party = ["poetry.core._vendor"] required-imports = ["from __future__ import annotations"] -[tool.black] -target-version = ['py38'] -preview = true -extend-exclude = "src/poetry/core/_vendor/|tests/([^/]*/)*fixtures/" [tool.mypy] strict = true @@ -115,6 +122,7 @@ module = [ ] ignore_missing_imports = true + [tool.vendoring] destination = "src/poetry/core/_vendor/" requirements = "src/poetry/core/_vendor/vendor.txt" @@ -130,8 +138,3 @@ drop = [ "typing.*", "*/tests/" ] - -[build-system] -requires = [] -build-backend = "poetry.core.masonry.api" -backend-path = ["src"] From fdf1d50dde5e7b12363185da1ff999a2ee658083 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Fri, 29 Mar 2024 22:43:21 -0600 Subject: [PATCH 06/13] ci: normalize workflow names --- .github/workflows/{downstream.yml => downstream.yaml} | 0 .github/workflows/{release.yml => release.yaml} | 0 .github/workflows/{tests.yml => tests.yaml} | 0 .github/workflows/{update_licenses.yml => update-licenses.yaml} | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{downstream.yml => downstream.yaml} (100%) rename .github/workflows/{release.yml => release.yaml} (100%) rename .github/workflows/{tests.yml => tests.yaml} (100%) rename .github/workflows/{update_licenses.yml => update-licenses.yaml} (98%) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yaml similarity index 100% rename from .github/workflows/downstream.yml rename to .github/workflows/downstream.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yaml similarity index 100% rename from .github/workflows/release.yml rename to .github/workflows/release.yaml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yaml similarity index 100% rename from .github/workflows/tests.yml rename to .github/workflows/tests.yaml diff --git a/.github/workflows/update_licenses.yml b/.github/workflows/update-licenses.yaml similarity index 98% rename from .github/workflows/update_licenses.yml rename to .github/workflows/update-licenses.yaml index be1efb6b6..2bf3fecf7 100644 --- a/.github/workflows/update_licenses.yml +++ b/.github/workflows/update-licenses.yaml @@ -1,4 +1,4 @@ -name: "Update licenses" +name: Update Licenses on: workflow_dispatch: From d09a4786e23e171062fac9abec5ffa673830129b Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 14:09:54 -0600 Subject: [PATCH 07/13] tests: add missing fixture --- .../script_callable_legacy_table/README.rst | 2 ++ .../my_package/__init__.py | 1 + .../pyproject.toml | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/masonry/builders/fixtures/script_callable_legacy_table/README.rst create mode 100644 tests/masonry/builders/fixtures/script_callable_legacy_table/my_package/__init__.py create mode 100644 tests/masonry/builders/fixtures/script_callable_legacy_table/pyproject.toml diff --git a/tests/masonry/builders/fixtures/script_callable_legacy_table/README.rst b/tests/masonry/builders/fixtures/script_callable_legacy_table/README.rst new file mode 100644 index 000000000..f7fe15470 --- /dev/null +++ b/tests/masonry/builders/fixtures/script_callable_legacy_table/README.rst @@ -0,0 +1,2 @@ +My Package +========== diff --git a/tests/masonry/builders/fixtures/script_callable_legacy_table/my_package/__init__.py b/tests/masonry/builders/fixtures/script_callable_legacy_table/my_package/__init__.py new file mode 100644 index 000000000..10aa336ce --- /dev/null +++ b/tests/masonry/builders/fixtures/script_callable_legacy_table/my_package/__init__.py @@ -0,0 +1 @@ +__version__ = "1.2.3" diff --git a/tests/masonry/builders/fixtures/script_callable_legacy_table/pyproject.toml b/tests/masonry/builders/fixtures/script_callable_legacy_table/pyproject.toml new file mode 100644 index 000000000..4f2ec00be --- /dev/null +++ b/tests/masonry/builders/fixtures/script_callable_legacy_table/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "my-package" +version = "1.2.3" +description = "Some description." +authors = [ + "Poetry Maintainers " +] +license = "MIT" +readme = "README.rst" + +[tool.poetry.dependencies] +python = "^3.6" + +[tool.poetry.dev-dependencies] + +[tool.poetry.extras] + +[tool.poetry.scripts] +script-legacy = { callable = "my_package:main" } From 50471821d543321600373152a3a4e359247af30a Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Fri, 29 Mar 2024 23:05:49 -0600 Subject: [PATCH 08/13] tests: add github-actions-annotate-failures --- poetry.lock | 19 +++++++++++++++++-- pyproject.toml | 6 ++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 64e272c30..082209fe8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "attrs" @@ -654,6 +654,20 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "pytest-github-actions-annotate-failures" +version = "0.1.8" +description = "pytest plugin to annotate failed tests with a workflow command for GitHub Actions" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +files = [ + {file = "pytest-github-actions-annotate-failures-0.1.8.tar.gz", hash = "sha256:2d6e6cb5f8d0aae4a27a20cc4e20fabd3199a121c57f44bc48fe28e372e0be23"}, + {file = "pytest_github_actions_annotate_failures-0.1.8-py2.py3-none-any.whl", hash = "sha256:6a882ff21672fa79deae8d917eb965a6bde2b25191e7632e1adfc23ffac008ab"}, +] + +[package.dependencies] +pytest = ">=4.0.0" + [[package]] name = "pytest-mock" version = "3.12.0" @@ -696,6 +710,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1041,4 +1056,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "f735bca440c1c1eeba822e475315a9c86fcb2cbb4f9aa3cd6920527cb9a5a55d" +content-hash = "13045fe9c4100dcfa6418df19957707297d712304fd92292f1c962968b44de1f" diff --git a/pyproject.toml b/pyproject.toml index 34bd7a86f..5564b5948 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,12 @@ virtualenv = ">=20.21" mypy = ">=1.0" types-setuptools = ">=57.4.14" +# only used in github actions +[tool.poetry.group.github-actions] +optional = true +[tool.poetry.group.github-actions.dependencies] +pytest-github-actions-annotate-failures = "^0.1.7" + [build-system] requires = [] From 1a414156fd7d4ae8c3ed8de1fc3bcaccf76e4901 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sat, 30 Mar 2024 00:34:35 -0600 Subject: [PATCH 09/13] tests: run in parallel with xdist (and randomize order) --- poetry.lock | 610 ++++++++++++++++++++++++++++--------------------- pyproject.toml | 6 + 2 files changed, 351 insertions(+), 265 deletions(-) diff --git a/poetry.lock b/poetry.lock index 082209fe8..705626ed8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -21,37 +21,38 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p [[package]] name = "build" -version = "1.0.3" +version = "1.2.1" description = "A simple, correct Python build frontend" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" files = [ - {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"}, - {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"}, + {file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"}, + {file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"}, ] [package.dependencies] colorama = {version = "*", markers = "os_name == \"nt\""} -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} -packaging = ">=19.0" +importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""} +packaging = ">=19.1" pyproject_hooks = "*" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"] -test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"] -typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"] +test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"] +typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"] +uv = ["uv (>=0.1.18)"] virtualenv = ["virtualenv (>=20.0.35)"] [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -191,63 +192,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.0" +version = "7.4.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, - {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, - {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, - {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, - {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, - {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, - {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, - {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, - {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, - {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, - {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, - {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, - {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, - {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, + {file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"}, + {file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"}, + {file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"}, + {file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"}, + {file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"}, + {file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"}, + {file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"}, + {file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"}, + {file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"}, + {file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"}, + {file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"}, + {file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"}, + {file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"}, + {file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"}, ] [package.dependencies] @@ -281,31 +282,45 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "execnet" +version = "2.0.2" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.7" +files = [ + {file = "execnet-2.0.2-py3-none-any.whl", hash = "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41"}, + {file = "execnet-2.0.2.tar.gz", hash = "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + [[package]] name = "filelock" -version = "3.13.1" +version = "3.13.3" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, - {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, + {file = "filelock-3.13.3-py3-none-any.whl", hash = "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb"}, + {file = "filelock-3.13.3.tar.gz", hash = "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] name = "identify" -version = "2.5.33" +version = "2.5.35" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, - {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, ] [package.extras] @@ -324,32 +339,32 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.0.1" +version = "7.1.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, - {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, + {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, + {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "importlib-resources" -version = "6.1.1" +version = "6.4.0" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, - {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, + {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, + {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, ] [package.dependencies] @@ -357,7 +372,7 @@ zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] +testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] [[package]] name = "iniconfig" @@ -445,38 +460,38 @@ files = [ [[package]] name = "mypy" -version = "1.8.0" +version = "1.9.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, - {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, - {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, - {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, - {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, - {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, - {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, - {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, - {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, - {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, - {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, - {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, - {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, - {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, - {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, - {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, - {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, - {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, - {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, + {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, + {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, + {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, + {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, + {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, + {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, + {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, + {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, + {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, + {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, + {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, + {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, + {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, + {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, + {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, + {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, + {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, + {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, + {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, ] [package.dependencies] @@ -517,13 +532,13 @@ setuptools = "*" [[package]] name = "packaging" -version = "23.2" +version = "24.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] [[package]] @@ -539,28 +554,28 @@ files = [ [[package]] name = "platformdirs" -version = "4.1.0" +version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] [[package]] name = "pluggy" -version = "1.3.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -585,6 +600,34 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "psutil" +version = "5.9.8" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, + {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, + {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, + {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, + {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, + {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, + {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, + {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, + {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, + {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + [[package]] name = "pygments" version = "2.17.2" @@ -616,13 +659,13 @@ tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [[package]] name = "pytest" -version = "7.4.4" +version = "8.1.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, + {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, ] [package.dependencies] @@ -630,21 +673,21 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.4,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.1.0" +version = "5.0.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [package.dependencies] @@ -652,7 +695,7 @@ coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-github-actions-annotate-failures" @@ -670,21 +713,57 @@ pytest = ">=4.0.0" [[package]] name = "pytest-mock" -version = "3.12.0" +version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, - {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, ] [package.dependencies] -pytest = ">=5.0" +pytest = ">=6.2.5" [package.extras] dev = ["pre-commit", "pytest-asyncio", "tox"] +[[package]] +name = "pytest-randomly" +version = "3.15.0" +description = "Pytest plugin to randomly order tests and control random.seed." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_randomly-3.15.0-py3-none-any.whl", hash = "sha256:0516f4344b29f4e9cdae8bce31c4aeebf59d0b9ef05927c33354ff3859eeeca6"}, + {file = "pytest_randomly-3.15.0.tar.gz", hash = "sha256:b908529648667ba5e54723088edd6f82252f540cc340d748d1fa985539687047"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +pytest = "*" + +[[package]] +name = "pytest-xdist" +version = "3.5.0" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.5.0.tar.gz", hash = "sha256:cbb36f3d67e0c478baa57fa4edc8843887e0f6cfc42d677530a36d7472b32d8a"}, + {file = "pytest_xdist-3.5.0-py3-none-any.whl", hash = "sha256:d075629c7e00b611df89f490a5063944bee7a4362a5ff11c7cc7824a03dfce24"}, +] + +[package.dependencies] +execnet = ">=1.1" +psutil = {version = ">=3.0", optional = true, markers = "extra == \"psutil\""} +pytest = ">=6.2.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + [[package]] name = "pyyaml" version = "6.0.1" @@ -747,13 +826,13 @@ files = [ [[package]] name = "referencing" -version = "0.32.1" +version = "0.34.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.32.1-py3-none-any.whl", hash = "sha256:7e4dc12271d8e15612bfe35792f5ea1c40970dadf8624602e33db2758f7ee554"}, - {file = "referencing-0.32.1.tar.gz", hash = "sha256:3c57da0513e9563eb7e203ebe9bb3a1b509b042016433bd1e45a2853466c3dd3"}, + {file = "referencing-0.34.0-py3-none-any.whl", hash = "sha256:d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4"}, + {file = "referencing-0.34.0.tar.gz", hash = "sha256:5773bd84ef41799a5a8ca72dc34590c041eb01bf9aa02632b4a973fb0181a844"}, ] [package.dependencies] @@ -783,13 +862,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.7.0" +version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, - {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, ] [package.dependencies] @@ -802,127 +881,127 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.17.1" +version = "0.18.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, - {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, - {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, - {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, - {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, - {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, - {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, - {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, - {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, - {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, - {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, - {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, - {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] [[package]] name = "setuptools" -version = "69.0.3" +version = "69.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, - {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, + {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"}, + {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "toml" @@ -959,39 +1038,40 @@ files = [ [[package]] name = "types-setuptools" -version = "69.0.0.20240115" +version = "69.2.0.20240317" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-69.0.0.20240115.tar.gz", hash = "sha256:1a9c863899f40cbe2053d0cd1d00ddef0330b492335467d018f73c1fec9462a3"}, - {file = "types_setuptools-69.0.0.20240115-py3-none-any.whl", hash = "sha256:7409e774c69e1810cb45052dbaed839fc30302e86a3ff945172ef2a2e7ab46f8"}, + {file = "types-setuptools-69.2.0.20240317.tar.gz", hash = "sha256:b607c4c48842ef3ee49dc0c7fe9c1bad75700b071e1018bb4d7e3ac492d47048"}, + {file = "types_setuptools-69.2.0.20240317-py3-none-any.whl", hash = "sha256:cf91ff7c87ab7bf0625c3f0d4d90427c9da68561f3b0feab77977aaf0bbf7531"}, ] [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] name = "urllib3" -version = "2.1.0" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -1020,13 +1100,13 @@ test = ["pytest", "pytest-cov", "pytest-mock"] [[package]] name = "virtualenv" -version = "20.25.0" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, - {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] @@ -1040,20 +1120,20 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "zipp" -version = "3.17.0" +version = "3.18.1" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, + {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, + {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "13045fe9c4100dcfa6418df19957707297d712304fd92292f1c962968b44de1f" +content-hash = "2f362a412908dac4c4557134d0a0eaf7bb90f85978740e7fc86e8e6d2ad47caa" diff --git a/pyproject.toml b/pyproject.toml index 5564b5948..d647bc99d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,8 @@ vendoring = ">=1.0" pytest = ">=7.1.2" pytest-cov = ">=3.0.0" pytest-mock = ">=3.10" +pytest-randomly = "^3.12" +pytest-xdist = { version = "^3.1", extras = ["psutil"] } build = ">=0.10.0" setuptools = ">=60" tomli-w = "^1.0.0" @@ -129,6 +131,10 @@ module = [ ignore_missing_imports = true +[tool.pytest.ini_options] +addopts = "-n logical" + + [tool.vendoring] destination = "src/poetry/core/_vendor/" requirements = "src/poetry/core/_vendor/vendor.txt" From f10c230e35e4488a01b91247b7d0f9356b765758 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 19:59:43 -0600 Subject: [PATCH 10/13] tests: disable the legacy tmpdir fixture --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d647bc99d..0fb3a5b5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -132,7 +132,8 @@ ignore_missing_imports = true [tool.pytest.ini_options] -addopts = "-n logical" +addopts = "-n logical -p no:legacypath" +testpaths = ["tests"] [tool.vendoring] From cd734e64234ff644336a4a7359386e739426f8e9 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sat, 30 Mar 2024 00:14:12 -0600 Subject: [PATCH 11/13] ci: add composite actions from poetry --- .github/actions/bootstrap-poetry/action.yaml | 48 +++++++++++++++++ .github/actions/poetry-install/action.yaml | 57 ++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 .github/actions/bootstrap-poetry/action.yaml create mode 100644 .github/actions/poetry-install/action.yaml diff --git a/.github/actions/bootstrap-poetry/action.yaml b/.github/actions/bootstrap-poetry/action.yaml new file mode 100644 index 000000000..cec135d89 --- /dev/null +++ b/.github/actions/bootstrap-poetry/action.yaml @@ -0,0 +1,48 @@ +name: Bootstrap Poetry +description: Configure the environment with the specified Python and Poetry version. + +inputs: + python-version: + description: Desired node-semver compatible Python version expression (or 'default') + default: 'default' + python-latest: + description: Use an uncached Python if a newer match is available + default: 'false' + python-prereleases: + description: Allow usage of pre-release Python versions + default: 'false' + poetry-spec: + description: pip-compatible installation specification to use for Poetry + default: 'poetry' + +outputs: + python-path: + description: Path to the installed Python interpreter + value: ${{ steps.setup-python.outputs.python-path }} + python-version: + description: Version of the installed Python interpreter + value: ${{ steps.setup-python.outputs.python-version }} + +runs: + using: composite + steps: + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + id: setup-python + if: inputs.python-version != 'default' + with: + python-version: ${{ inputs.python-version }} + check-latest: ${{ inputs.python-latest == 'true' }} + allow-prereleases: ${{ inputs.python-prereleases == 'true' }} + update-environment: false + + - run: > + pipx install \ + ${{ inputs.python-version != 'default' && format('--python "{0}"', steps.setup-python.outputs.python-path) || '' }} \ + '${{ inputs.poetry-spec }}' + shell: bash + + # Enable handling long path names (+260 char) on the Windows platform + # https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation + - run: git config --system core.longpaths true + if: runner.os == 'Windows' + shell: pwsh diff --git a/.github/actions/poetry-install/action.yaml b/.github/actions/poetry-install/action.yaml new file mode 100644 index 000000000..9436303e3 --- /dev/null +++ b/.github/actions/poetry-install/action.yaml @@ -0,0 +1,57 @@ +name: Poetry Install +description: Run `poetry install` with optional artifact and metadata caching + +inputs: + args: + description: Arguments for `poetry install` + cache: + description: Enable transparent Poetry artifact and metadata caching + default: 'true' + path: + description: Path to Poetry project + default: '.' + +outputs: + cache-hit: + description: Whether an exact cache hit occured + value: ${{ steps.cache.outputs.cache-hit }} + +defaults: + run: + working-directory: ${{ inputs.path }} + +runs: + using: composite + steps: + - run: printf 'cache-dir=%s\n' "$(poetry config cache-dir)" >> $GITHUB_OUTPUT + id: poetry-config + shell: bash + + # Bust the cache every 24 hours to prevent it from expanding over time. + - run: printf 'date=%s\n' "$(date -I)" >> $GITHUB_OUTPUT + id: get-date + if: inputs.cache == 'true' + shell: bash + + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + id: cache + if: inputs.cache == 'true' + with: + path: | + ${{ steps.poetry-config.outputs.cache-dir }}/artifacts + ${{ steps.poetry-config.outputs.cache-dir }}/cache + key: poetry-${{ steps.get-date.outputs.date }}-${{ runner.os }}-${{ hashFiles(format('{0}/pyproject.toml', inputs.path), format('{0}/poetry.lock', inputs.path)) }} + # The cache is cross-platform, and other platforms are used to seed cache misses. + restore-keys: | + poetry-${{ steps.get-date.outputs.date }}-${{ runner.os }}- + poetry-${{ steps.get-date.outputs.date }}- + enableCrossOsArchive: true + + - run: poetry install ${{ inputs.args }} + shell: bash + + - run: poetry env info + shell: bash + + - run: poetry show + shell: bash From a9f44b7598565f46327af31fb15888b4041df1f4 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sat, 30 Mar 2024 00:14:27 -0600 Subject: [PATCH 12/13] ci/tests: modernize based on poetry --- .github/actions/bootstrap-poetry/action.yaml | 5 +- .github/actions/poetry-install/action.yaml | 7 +- .github/workflows/.tests-matrix.yaml | 95 ++++++++++++ .github/workflows/downstream.yaml | 76 --------- .github/workflows/tests.yaml | 153 +++++++++++-------- 5 files changed, 186 insertions(+), 150 deletions(-) create mode 100644 .github/workflows/.tests-matrix.yaml delete mode 100644 .github/workflows/downstream.yaml diff --git a/.github/actions/bootstrap-poetry/action.yaml b/.github/actions/bootstrap-poetry/action.yaml index cec135d89..1ab66f8c0 100644 --- a/.github/actions/bootstrap-poetry/action.yaml +++ b/.github/actions/bootstrap-poetry/action.yaml @@ -35,10 +35,7 @@ runs: allow-prereleases: ${{ inputs.python-prereleases == 'true' }} update-environment: false - - run: > - pipx install \ - ${{ inputs.python-version != 'default' && format('--python "{0}"', steps.setup-python.outputs.python-path) || '' }} \ - '${{ inputs.poetry-spec }}' + - run: pipx install ${{ inputs.python-version != 'default' && format('--python "{0}"', steps.setup-python.outputs.python-path) || '' }} '${{ inputs.poetry-spec }}' shell: bash # Enable handling long path names (+260 char) on the Windows platform diff --git a/.github/actions/poetry-install/action.yaml b/.github/actions/poetry-install/action.yaml index 9436303e3..37109a0de 100644 --- a/.github/actions/poetry-install/action.yaml +++ b/.github/actions/poetry-install/action.yaml @@ -16,10 +16,6 @@ outputs: description: Whether an exact cache hit occured value: ${{ steps.cache.outputs.cache-hit }} -defaults: - run: - working-directory: ${{ inputs.path }} - runs: using: composite steps: @@ -48,10 +44,13 @@ runs: enableCrossOsArchive: true - run: poetry install ${{ inputs.args }} + working-directory: ${{ inputs.path }} shell: bash - run: poetry env info + working-directory: ${{ inputs.path }} shell: bash - run: poetry show + working-directory: ${{ inputs.path }} shell: bash diff --git a/.github/workflows/.tests-matrix.yaml b/.github/workflows/.tests-matrix.yaml new file mode 100644 index 000000000..b3b668a40 --- /dev/null +++ b/.github/workflows/.tests-matrix.yaml @@ -0,0 +1,95 @@ +# Reusable workflow consumed by tests.yaml; used to share a single matrix across jobs. +on: + workflow_call: + inputs: + runner: + required: true + type: string + python-version: + required: true + type: string + run-mypy: + required: true + type: boolean + run-pytest: + required: true + type: boolean + run-pytest-poetry: + required: true + type: boolean + +defaults: + run: + shell: bash + +jobs: + mypy: + name: mypy + runs-on: ${{ inputs.runner }} + if: inputs.run-mypy + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - uses: ./.github/actions/bootstrap-poetry + id: bootstrap-poetry + with: + python-version: ${{ inputs.python-version }} + + - uses: ./.github/actions/poetry-install + + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + with: + path: .mypy_cache + key: mypy-${{ runner.os }}-py${{ steps.bootstrap-poetry.outputs.python-version }}-${{ hashFiles('pyproject.toml', 'poetry.lock') }} + restore-keys: | + mypy-${{ runner.os }}-py${{ steps.bootstrap-poetry.outputs.python-version }}- + mypy-${{ runner.os }}- + + - run: poetry run mypy + + pytest: + name: pytest + runs-on: ${{ inputs.runner }} + if: inputs.run-pytest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - uses: ./.github/actions/bootstrap-poetry + with: + python-version: ${{ inputs.python-version }} + + - uses: ./.github/actions/poetry-install + with: + args: --with github-actions + + - run: poetry run pytest --integration -v + + - run: git diff --exit-code --stat HEAD + + pytest-poetry: + name: pytest (Poetry) + runs-on: ${{ inputs.runner }} + if: inputs.run-pytest-poetry + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + path: poetry-core + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + path: poetry + repository: python-poetry/poetry + + - uses: ./poetry-core/.github/actions/bootstrap-poetry + with: + python-version: ${{ inputs.python-version }} + + - uses: ./poetry-core/.github/actions/poetry-install + with: + path: ./poetry + + - run: poetry add ../poetry-core + working-directory: ./poetry + + - run: poetry run pytest -v + working-directory: ./poetry diff --git a/.github/workflows/downstream.yaml b/.github/workflows/downstream.yaml deleted file mode 100644 index 9e53293c8..000000000 --- a/.github/workflows/downstream.yaml +++ /dev/null @@ -1,76 +0,0 @@ -name: Poetry Downstream Tests - -on: - pull_request: {} - push: - branches: [main] - -jobs: - tests: - name: ${{ matrix.ref }} - runs-on: ubuntu-latest - strategy: - matrix: - ref: ["main"] - fail-fast: false - defaults: - run: - shell: bash - steps: - - uses: actions/checkout@v4 - with: - path: poetry-core - - - uses: actions/checkout@v4 - with: - path: poetry - repository: python-poetry/poetry - ref: ${{ matrix.ref }} - - - name: Set up Python 3.10 - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - - name: Get full python version - id: full-python-version - run: echo version=$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") >> $GITHUB_OUTPUT - - - name: Set up Poetry - run: | - pip install poetry - poetry config virtualenvs.in-project true - - - name: Set up cache - uses: actions/cache@v4 - id: cache - with: - path: ./poetry/.venv - key: venv-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - - name: Ensure cache is healthy - if: steps.cache.outputs.cache-hit == 'true' - working-directory: ./poetry - run: timeout 10s poetry run pip --version >/dev/null 2>&1 || rm -rf .venv - - - name: Switch downstream to development poetry-core - working-directory: ./poetry - run: | - # remove poetry-core from main group to avoid version conflicts - # with a potential entry in the test group - poetry remove poetry-core - # add to test group to overwrite a potential entry in that group - poetry add --lock --group test ../poetry-core - - - name: Install downstream dependencies - working-directory: ./poetry - run: | - # force update of directory dependency in cached venv - # (even if directory dependency with same version is already installed) - poetry run pip uninstall -y poetry-core - poetry install - - # TODO: mark run as success even when this fails and add comment to PR instead - - name: Run downstream test suite - working-directory: ./poetry - run: poetry run pytest diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 42a7b9a56..848439558 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,81 +1,102 @@ name: Tests on: - pull_request: {} + merge_group: + pull_request: push: - branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +defaults: + run: + shell: bash env: PYTHONWARNDEFAULTENCODING: 'true' jobs: - tests: - name: ${{ matrix.os }} / ${{ matrix.python-version }} - runs-on: "${{ matrix.os }}-latest" + changes: + name: Detect changed files + runs-on: ubuntu-latest + outputs: + project: ${{ steps.changes.outputs.project }} + src: ${{ steps.changes.outputs.src }} + tests: ${{ steps.changes.outputs.tests }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3 + id: changes + with: + filters: | + workflow: &workflow + - '.github/actions/**' + - '.github/workflows/tests.yaml' + - '.github/workflows/.tests-matrix.yaml' + project: &project + - *workflow + - 'poetry.lock' + - 'pyproject.toml' + src: + - *project + - 'src/**/*.py' + tests: + - *project + - 'src/**/*.py' + - 'tests/**' + + lockfile: + name: Check poetry.lock + runs-on: ubuntu-latest + if: needs.changes.outputs.project == 'true' + needs: changes + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - uses: ./.github/actions/bootstrap-poetry + + - run: poetry check --lock + + tests-matrix: + # Use this matrix with multiple jobs defined in a reusable workflow: + uses: ./.github/workflows/.tests-matrix.yaml + name: ${{ matrix.os.name }} (Python ${{ matrix.python-version }}) + if: '!failure() && !cancelled()' + needs: + - lockfile + - changes + with: + runner: ${{ matrix.os.image }} + python-version: ${{ matrix.python-version }} + run-mypy: ${{ needs.changes.outputs.src == 'true' }} + run-pytest: ${{ needs.changes.outputs.tests == 'true' }} + run-pytest-poetry: ${{ needs.changes.outputs.src == 'true' }} + secrets: inherit strategy: matrix: - os: [Ubuntu, MacOS, Windows] + os: + - name: Ubuntu + image: ubuntu-22.04 + - name: macOS + image: macos-13 + - name: Windows + image: windows-2022 python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] include: - - os: Ubuntu - python-version: pypy-3.8 + - os: {name: Ubuntu, image: ubuntu-22.04} + python-version: pypy3.9 + - os: {name: Ubuntu, image: ubuntu-22.04} + python-version: pypy3.10 fail-fast: false - defaults: - run: - shell: bash - steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Get full Python version - id: full-python-version - run: echo version=$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") >> $GITHUB_OUTPUT - - - name: Bootstrap poetry - run: | - curl -sSL https://install.python-poetry.org | python - -y - - name: Update PATH - if: ${{ matrix.os != 'Windows' }} - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Update Path for Windows - if: ${{ matrix.os == 'Windows' }} - run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH - - - name: Configure poetry - run: poetry config virtualenvs.in-project true - - - name: Set up cache - uses: actions/cache@v4 - id: cache - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - - name: Ensure cache is healthy - if: steps.cache.outputs.cache-hit == 'true' - run: | - # `timeout` is not available on macOS, so we define a custom function. - [ "$(command -v timeout)" ] || function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; } - # Using `timeout` is a safeguard against the Poetry command hanging for some reason. - timeout 10s poetry run pip --version || rm -rf .venv - - - name: Check lock file - run: poetry lock --check - - - name: Install dependencies - run: poetry install - - - name: Run tests - run: poetry run python -m pytest -p no:sugar -q tests/ - - - name: Run integration tests - run: poetry run python -m pytest -p no:sugar --integration -q tests/integration - - - name: Run mypy - run: poetry run mypy + status: + name: Status + runs-on: ubuntu-latest + if: '!cancelled()' + needs: + - lockfile + - tests-matrix + steps: + - run: ${{ (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && 'false' || 'true' }} From 7539d837373bda86084434757c3b5db8abba76fd Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Sun, 31 Mar 2024 20:09:12 -0600 Subject: [PATCH 13/13] ci/tests: skip downstream tests on pypy --- .github/workflows/.tests-matrix.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/.tests-matrix.yaml b/.github/workflows/.tests-matrix.yaml index b3b668a40..17cfa2c70 100644 --- a/.github/workflows/.tests-matrix.yaml +++ b/.github/workflows/.tests-matrix.yaml @@ -69,7 +69,8 @@ jobs: pytest-poetry: name: pytest (Poetry) runs-on: ${{ inputs.runner }} - if: inputs.run-pytest-poetry + # FIXME: make Poetry tests pass with PyPy + if: inputs.run-pytest-poetry && !startsWith(inputs.python-version, 'pypy') steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: