From 14074c9f72db2ed73a9d26bfd17e1672872ef5dc Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sun, 27 Jul 2025 11:29:58 +0200 Subject: [PATCH 1/3] Move pytest-mypy-plugins tests into mypy jobs Those tests are very slow and break under pytest-xdist. --- pyproject.toml | 7 +++-- tox.ini | 7 ++--- uv.lock | 70 ++++++++++++++++++++++++++------------------------ 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e395d6308..ad6ceae08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,14 +37,17 @@ Tidelift = "https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-att [dependency-groups] -tests-mypy = ['pytest-mypy-plugins; platform_python_implementation == "CPython" and python_version >= "3.10"'] +mypy = [ + { include-group = "tests" }, + 'pytest-mypy-plugins; platform_python_implementation == "CPython" and python_version >= "3.10"' +] tests = [ - { include-group = "tests-mypy" }, # For regression test to ensure cloudpickle compat doesn't break. 'cloudpickle; platform_python_implementation == "CPython"', "hypothesis", "pympler", "pytest", + "pytest-xdist[psutil]", ] cov = [ { include-group = "tests" }, diff --git a/tox.ini b/tox.ini index ad5adf2d5..71d4cc77f 100644 --- a/tox.ini +++ b/tox.ini @@ -21,9 +21,10 @@ package = wheel wheel_build_env = .pkg dependency_groups = tests: tests - mypy: tests-mypy + mypy: mypy commands = - tests: pytest {posargs} + tests: pytest {posargs:-n auto} + mypy: pytest -k test_mypy mypy: mypy tests/typing_example.py mypy: mypy src/attrs/__init__.pyi src/attr/__init__.pyi src/attr/_typing_compat.pyi src/attr/_version_info.pyi src/attr/converters.pyi src/attr/exceptions.pyi src/attr/filters.pyi src/attr/setters.pyi src/attr/validators.pyi @@ -39,7 +40,7 @@ set_env = COVERAGE_PROCESS_START={toxinidir}/pyproject.toml PYTHONWARNINGS=d commands = - coverage run -m pytest {posargs} + coverage run -m pytest {posargs:-n auto} [testenv:coverage-report] # Keep base_python in-sync with .python-version-default diff --git a/uv.lock b/uv.lock index 7e49ce590..8b97dc64a 100644 --- a/uv.lock +++ b/uv.lock @@ -2,8 +2,7 @@ version = 1 revision = 2 requires-python = ">=3.9" resolution-markers = [ - "python_full_version >= '3.14' and platform_python_implementation == 'CPython'", - "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation == 'CPython'", + "python_full_version >= '3.11' and platform_python_implementation == 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation == 'CPython'", "python_full_version >= '3.11' and platform_python_implementation != 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation != 'CPython'", @@ -39,8 +38,7 @@ name = "alabaster" version = "1.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14' and platform_python_implementation == 'CPython'", - "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation == 'CPython'", + "python_full_version >= '3.11' and platform_python_implementation == 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation == 'CPython'", "python_full_version >= '3.11' and platform_python_implementation != 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation != 'CPython'", @@ -76,7 +74,6 @@ benchmark = [ { name = "pympler" }, { name = "pytest" }, { name = "pytest-codspeed" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, { name = "pytest-xdist", extra = ["psutil"] }, ] cov = [ @@ -85,14 +82,14 @@ cov = [ { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extra = ["psutil"] }, ] dev = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extra = ["psutil"] }, ] docs = [ { name = "cogapp" }, @@ -119,23 +116,28 @@ docs-watch = [ { name = "towncrier" }, { name = "watchfiles" }, ] +mypy = [ + { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, + { name = "hypothesis" }, + { name = "pympler" }, + { name = "pytest" }, + { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extra = ["psutil"] }, +] pyright = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pyright" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extra = ["psutil"] }, ] tests = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, -] -tests-mypy = [ - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extra = ["psutil"] }, ] [package.metadata] @@ -147,7 +149,6 @@ benchmark = [ { name = "pympler" }, { name = "pytest" }, { name = "pytest-codspeed" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, { name = "pytest-xdist", extras = ["psutil"] }, ] cov = [ @@ -156,14 +157,14 @@ cov = [ { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extras = ["psutil"] }, ] dev = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extras = ["psutil"] }, ] docs = [ { name = "cogapp" }, @@ -184,22 +185,29 @@ docs-watch = [ { name = "towncrier" }, { name = "watchfiles" }, ] +mypy = [ + { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, + { name = "hypothesis" }, + { name = "pympler" }, + { name = "pytest" }, + { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extras = ["psutil"] }, +] pyright = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pyright" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extras = ["psutil"] }, ] tests = [ { name = "cloudpickle", marker = "platform_python_implementation == 'CPython'" }, { name = "hypothesis" }, { name = "pympler" }, { name = "pytest" }, - { name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }, + { name = "pytest-xdist", extras = ["psutil"] }, ] -tests-mypy = [{ name = "pytest-mypy-plugins", marker = "python_full_version >= '3.10' and platform_python_implementation == 'CPython'" }] [[package]] name = "babel" @@ -395,8 +403,7 @@ name = "click" version = "8.2.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14' and platform_python_implementation == 'CPython'", - "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation == 'CPython'", + "python_full_version >= '3.11' and platform_python_implementation == 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation == 'CPython'", "python_full_version >= '3.11' and platform_python_implementation != 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation != 'CPython'", @@ -559,7 +566,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -595,16 +602,16 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.136.0" +version = "6.136.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/5d/43cb4bb94f038d4ccdbbd7f3572c000413dde8949ab77fd476897762dc6e/hypothesis-6.136.0.tar.gz", hash = "sha256:1d7f0b61195369c043b90484cb2948a369ff83b3584970586d5c9a6f60641625", size = 456682, upload-time = "2025-07-19T04:12:45.969Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/e2/ebee1678151e8f06f84f10e74229060b5db9f16fd4cac35b44a8286aa669/hypothesis-6.136.4.tar.gz", hash = "sha256:56bf16ba20d39ad7c5f8d3c42a5a7503844a7892dbf6f6e6e79b2188319a56d8", size = 457805, upload-time = "2025-07-25T02:38:14.341Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/b6/0a7e1f0e79da9396968338d501b5c72c81d70187679d8c57ed349df5d579/hypothesis-6.136.0-py3-none-any.whl", hash = "sha256:a288672440d94f9cd307e3889c4087d1f8c8b114285fcf07ae415b3c7d4a26ab", size = 523667, upload-time = "2025-07-19T04:12:41.761Z" }, + { url = "https://files.pythonhosted.org/packages/8a/95/bcdf24ac537b46d49b73c6a7e9f3b0d66016958299d36c41636afa9187cd/hypothesis-6.136.4-py3-none-any.whl", hash = "sha256:488156d3603a9db6218ab2bf68d75e0fd967671a676ecc478c6b44eb153a7527", size = 524759, upload-time = "2025-07-25T02:38:10.278Z" }, ] [[package]] @@ -630,7 +637,7 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.10'" }, + { name = "zipp", marker = "python_full_version < '3.10' or platform_python_implementation != 'CPython'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ @@ -877,8 +884,7 @@ name = "myst-parser" version = "4.0.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14' and platform_python_implementation == 'CPython'", - "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation == 'CPython'", + "python_full_version >= '3.11' and platform_python_implementation == 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation == 'CPython'", "python_full_version >= '3.11' and platform_python_implementation != 'CPython'", "python_full_version == '3.10.*' and platform_python_implementation != 'CPython'", @@ -1266,16 +1272,15 @@ wheels = [ [[package]] name = "rich" -version = "14.0.0" +version = "14.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, + { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, ] [[package]] @@ -1543,8 +1548,7 @@ name = "sphinx" version = "8.2.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14' and platform_python_implementation == 'CPython'", - "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation == 'CPython'", + "python_full_version >= '3.11' and platform_python_implementation == 'CPython'", "python_full_version >= '3.11' and platform_python_implementation != 'CPython'", ] dependencies = [ From f1071707d7725a9b84076b07969dfea24a0edce4 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sun, 27 Jul 2025 11:37:25 +0200 Subject: [PATCH 2/3] Apply Coverage 7.10 feature --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ad6ceae08..9c94d34e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,6 +165,7 @@ filterwarnings = ["once::Warning", "ignore:::pympler[.*]"] [tool.coverage.run] parallel = true branch = true +patch = "subprocess" source_pkgs = ["attr", "attrs"] [tool.coverage.paths] From 486574c915765121f5419bf15dcd6ba929fe4ad9 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sun, 27 Jul 2025 11:40:35 +0200 Subject: [PATCH 3/3] it's a list! --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9c94d34e4..4184fd548 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,7 +165,7 @@ filterwarnings = ["once::Warning", "ignore:::pympler[.*]"] [tool.coverage.run] parallel = true branch = true -patch = "subprocess" +patch = ["subprocess"] source_pkgs = ["attr", "attrs"] [tool.coverage.paths]