Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a fully locked test environment #1349

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
21 changes: 7 additions & 14 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,12 @@ build:
tools:
# Keep version in sync with tox.ini/docs and ci.yml/docs.
python: "3.13"
jobs:
commands:
# Need the tags to calculate the version (sometimes).
post_checkout:
- git fetch --tags
- git fetch --tags
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest

# Replace versions in sponsor URLs.
pre_build:
- python -Im pip install tox-uv
- python -Im tox run -e docs-sponsors

python:
install:
- method: pip
path: .
extra_requirements:
- docs
- uvx --with tox-uv tox run -e docs-sponsors
- uvx --with tox-uv tox run -e docs -- $READTHEDOCS_OUTPUT
42 changes: 23 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ description = "Classes Without Boilerplate"
keywords = ["class", "attribute", "boilerplate"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -28,29 +27,41 @@ classifiers = [
dependencies = []
dynamic = ["version", "readme"]

[project.optional-dependencies]
[project.urls]
Documentation = "https://www.attrs.org/"
Changelog = "https://www.attrs.org/en/stable/changelog.html"
GitHub = "https://github.com/python-attrs/attrs"
Funding = "https://github.com/sponsors/hynek"
Tidelift = "https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi"


[dependency-groups]
tests-mypy = [
'pytest-mypy-plugins; platform_python_implementation == "CPython" and python_version >= "3.10"',
# Since the mypy error messages keep changing, we have to keep updating this
# pin.
'mypy>=1.11.1; 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",
# 4.3.0 dropped last use of `convert`
"pytest>=4.3.0",
"pytest-xdist[psutil]",
"attrs[tests-mypy]",
]
cov = [
"attrs[tests]",
{ include-group = "tests" },
# Ensure coverage is new enough for `source_pkgs`.
"coverage[toml]>=5.3",
]
benchmark = ["pytest-codspeed", "pytest-xdist[psutil]", "attrs[tests]"]
pyright = ["pyright", { include-group = "tests" }]
benchmark = [
{ include-group = "tests" },
"pytest-codspeed",
"pytest-xdist[psutil]",
]
docs = [
"cogapp",
"furo",
Expand All @@ -59,17 +70,10 @@ docs = [
"sphinx-notfound-page",
"sphinxcontrib-towncrier",
# See https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92
# Pin also present in tox.ini
"towncrier<24.7",
]
dev = ["attrs[tests]", "pre-commit-uv"]

[project.urls]
Documentation = "https://www.attrs.org/"
Changelog = "https://www.attrs.org/en/stable/changelog.html"
GitHub = "https://github.com/python-attrs/attrs"
Funding = "https://github.com/sponsors/hynek"
Tidelift = "https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi"
docs-watch = [{ include-group = "docs" }, "watchfiles"]
dev = [{ include-group = "tests" }]


[tool.hatch.version]
Expand Down Expand Up @@ -249,10 +253,10 @@ ignore = [
"src/*/*.pyi" = ["ALL"] # TODO
"tests/test_annotations.py" = ["FA100"]
"tests/typing_example.py" = [
"E741", # ambiguous variable names don't matter in type checks
"B018", # useless expressions aren't useless in type checks
"B015", # pointless comparison in type checks aren't pointless
"UP037", # we test some older syntaxes on purpose
"E741", # ambiguous variable names don't matter in type checks
"B018", # useless expressions aren't useless in type checks
"B015", # pointless comparison in type checks aren't pointless
"UP037", # we test some older syntaxes on purpose
]

[tool.ruff.lint.isort]
Expand Down
48 changes: 25 additions & 23 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,47 @@ pass_env = SETUPTOOLS_SCM_PRETEND_VERSION


[testenv]
runner = uv-venv-lock-runner
package = wheel
wheel_build_env = .pkg
extras =
dependency_groups =
tests: tests
mypy: tests-mypy
commands =
tests: pytest {posargs:-n auto}
tests: pytest {posargs}
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

[testenv:pypy3-tests]
extras = tests
dependency_groups = tests
commands = pytest tests/test_functional.py

[testenv:py3{8,10,13}-tests]
extras = cov
dependency_groups = cov
# Python 3.6+ has a number of compile-time warnings on invalid string escapes.
# PYTHONWARNINGS=d makes them visible during the tox run.
set_env =
COVERAGE_PROCESS_START={toxinidir}/pyproject.toml
PYTHONWARNINGS=d
commands_pre = python -c 'import pathlib; pathlib.Path("{env_site_packages_dir}/cov.pth").write_text("import coverage; coverage.process_startup()")'
# We group xdist execution by file because otherwise the Mypy tests have race conditions.
commands = coverage run -m pytest {posargs:-n auto --dist loadfile}
commands =
uv pip list -p {envpython}
coverage run -m pytest {posargs}

[testenv:coverage-report]
# Keep base_python in-sync with .python-version-default
base_python = py313
# Keep depends in-sync with testenv above that has cov extra.
# Keep depends in-sync with testenv above that has the cov dependency group.
depends = py3{8,10,13}-tests
skip_install = true
deps = coverage[toml]>=5.3
dependency_groups = cov
commands =
coverage combine
coverage report


[testenv:codspeed]
extras = benchmark
dependency_groups = benchmark
pass_env =
CODSPEED_TOKEN
CODSPEED_ENV
Expand All @@ -65,65 +67,65 @@ commands = pytest --codspeed -n auto bench/test_benchmarks.py


[testenv:docs]
runner = uv-venv-lock-runner
# Keep base_python in-sync with ci.yml/docs and .readthedocs.yaml.
base_python = py313
extras = docs
dependency_groups = docs
commands =
sphinx-build -n -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
sphinx-build -n -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
sphinx-build -n -T -W -b html -d {envtmpdir}/doctrees docs {posargs:docs/_build/}html
sphinx-build -n -T -W -b doctest -d {envtmpdir}/doctrees docs {posargs:docs/_build/}html


[testenv:docs-watch]
package = editable
base_python = {[testenv:docs]base_python}
extras = {[testenv:docs]extras}
deps = watchfiles
dependency_groups = docs-watch
commands =
watchfiles \
--ignore-paths docs/_build/ \
'sphinx-build -W -n --jobs auto -b html -d {envtmpdir}/doctrees docs docs/_build/html' \
README.md \
src \
docs


[testenv:docs-linkcheck]
package = editable
base_python = {[testenv:docs]base_python}
extras = {[testenv:docs]extras}
dependency_groups = {[testenv:docs]dependency_groups}
commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees docs docs/_build/html


[testenv:docs-sponsors]
runner = uv-venv-runner
skip_install = true
description = Ensure sponsor logos are up to date.
deps = cogapp
commands = cog -rP README.md docs/index.md


[testenv:pre-commit]
runner = uv-venv-runner
skip_install = true
deps = pre-commit-uv
commands = pre-commit run --all-files


[testenv:changelog]
# See https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92
# Pin also present in pyproject.toml
deps = towncrier<24.7
dependency_groups = docs
skip_install = true
commands =
towncrier --version
towncrier build --version main --draft


[testenv:pyright]
extras = tests
deps = pyright>=1.1.380
dependency_groups = pyright
commands = pytest tests/test_pyright.py -vv


[testenv:docset]
runner = uv-venv-runner
deps = doc2dash
extras = docs
dependency_groups = docs
allowlist_externals =
rm
cp
Expand Down
Loading
Loading