attrs/pyproject.toml

291 lines
8.1 KiB
TOML

# SPDX-License-Identifier: MIT
[build-system]
requires = ["hatchling", "hatch-vcs", "hatch-fancy-pypi-readme>=23.2.0"]
build-backend = "hatchling.build"
[project]
name = "attrs"
authors = [{ name = "Hynek Schlawack", email = "hs@ox.cx" }]
license = { text = "MIT" }
requires-python = ">=3.8"
description = "Classes Without Boilerplate"
keywords = ["class", "attribute", "boilerplate"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Typing :: Typed",
]
dependencies = []
dynamic = ["version", "readme"]
[project.optional-dependencies]
tests-mypy = [
'pytest-mypy-plugins; platform_python_implementation == "CPython" and python_version >= "3.9"',
# 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.9"',
]
tests = [
# 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]",
# Ensure coverage is new enough for `source_pkgs`.
"coverage[toml]>=5.3",
]
benchmark = ["pytest-codspeed", "pytest-xdist[psutil]", "attrs[tests]"]
docs = [
"cogapp",
"furo",
"myst-parser",
"sphinx",
"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"
[tool.hatch.version]
source = "vcs"
raw-options = { local_scheme = "no-local-version" }
[tool.hatch.build.targets.wheel]
packages = ["src/attr", "src/attrs"]
[tool.hatch.metadata.hooks.fancy-pypi-readme]
content-type = "text/markdown"
# PyPI doesn't support the <picture> tag.
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """<p align="center">
<a href="https://www.attrs.org/">
<img src="https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo.svg" width="35%" alt="attrs" />
</a>
</p>
"""
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "README.md"
start-after = "<!-- teaser-begin -->"
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """
## Release Information
"""
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "CHANGELOG.md"
pattern = "\n(###.+?\n)## "
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """
---
[Full changelog →](https://www.attrs.org/en/stable/changelog.html)
"""
# Point sponsor image URLs to versions.
[[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
pattern = 'docs\/_static\/sponsors'
replacement = 'https://www.attrs.org/en/$HFPR_VERSION/_static/sponsors'
[[tool.sponcon.sponsors]]
title = "Variomedia AG"
url = "https://www.variomedia.de/"
img = "Variomedia.svg"
[[tool.sponcon.sponsors]]
title = "Tidelift"
url = "https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"
img = "Tidelift.svg"
[[tool.sponcon.sponsors]]
title = "Klaviyo"
url = "https://klaviyo.com/"
img = "Klaviyo.svg"
[[tool.sponcon.sponsors]]
title = "FilePreviews"
url = "https://filepreviews.io/"
img = "FilePreviews.svg"
[[tool.sponcon.sponsors]]
title = "Polar"
url = "https://polar.sh/"
img = "Polar.svg"
[tool.pytest.ini_options]
addopts = ["-ra", "--strict-markers", "--strict-config"]
xfail_strict = true
testpaths = "tests"
filterwarnings = ["once::Warning", "ignore:::pympler[.*]"]
[tool.coverage.run]
parallel = true
branch = true
source_pkgs = ["attr", "attrs"]
[tool.coverage.paths]
source = ["src", ".tox/py*/**/site-packages"]
[tool.coverage.report]
show_missing = true
skip_covered = true
exclude_lines = [
"pragma: no cover",
# PyPy is unacceptably slow under coverage.
"if PYPY:",
# not meant to be executed
': \.\.\.$',
'^ +\.\.\.$',
]
[tool.interrogate]
omit-covered-files = true
verbose = 2
fail-under = 100
whitelist-regex = ["test_.*"]
[tool.check-wheel-contents]
toplevel = ["attr", "attrs"]
[tool.ruff]
src = ["src", "tests", "conftest.py", "docs"]
line-length = 79
[tool.ruff.lint]
select = ["ALL"]
ignore = [
"A001", # shadowing is fine
"A002", # shadowing is fine
"A003", # shadowing is fine
"ANN", # Mypy is better at this
"ARG", # unused arguments are normal when implementing interfaces
"C901", # we're complex software
"COM", # ruff format takes care of our commas
"D", # We prefer our own docstring style.
"E501", # leave line-length enforcement to ruff format
"ERA001", # we need to keep around some notes
"FBT", # we don't hate bool args around here
"FIX", # Yes, we want XXX as a marker.
"ISC001", # conflicts with ruff format
"N", # we need more naming freedom
"PD", # we're not pandas
"PLR0912", # we're complex software
"PLR0913", # yes, many arguments, but most have defaults
"PLR0915", # we're complex software
"PLR2004", # numbers are sometimes fine
"PLW0603", # sometimes we need globals
"S307", # eval FTW
"SLF001", # private members are accessed by friendly functions
"TCH", # TYPE_CHECKING blocks break autodocs
"TD", # we don't follow other people's todo style
"TRY301", # I'm sorry, but this makes not sense for us.
"UP031", # format() is slow as molasses; % and f'' FTW.
]
[tool.ruff.lint.per-file-ignores]
"bench/**" = [
"INP001", # Benchmarks don't have to be importable.
]
"**/test_*" = [
"B015", # pointless comparison in tests aren't pointless
"B017", # pytest.raises(Exception) is fine
"B018", # pointless expressions in tests aren't pointless
"DTZ", # datetime best practices don't matter in tests
"EM", # no need for exception msg hygiene in tests
"PLE0309", # hash doesn't have to return anything in tests
"PLR0124", # pointless comparison in tests aren't pointless
"PT011", # broad is fine
"PT012", # sometimes we need more than a single stmt
"RUF012", # we don't do ClassVar annotations in tests
"S", # security concerns don't matter in tests
"SIM201", # sometimes we need to check `not ==`
"SIM202", # sometimes we need to check `not ==`
"SIM300", # Yoda rocks in asserts
"TRY", # exception best practices don't matter in tests
]
"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
]
[tool.ruff.lint.isort]
lines-between-types = 1
lines-after-imports = 2
[tool.towncrier]
name = "attrs"
directory = "changelog.d"
filename = "CHANGELOG.md"
start_string = "<!-- towncrier release notes start -->\n"
template = "changelog.d/towncrier_template.md.jinja"
title_format = ""
issue_format = "[#{issue}](https://github.com/python-attrs/attrs/issues/{issue})"
underlines = ["", "", ""]
[[tool.towncrier.section]]
path = ""
[[tool.towncrier.type]]
directory = "breaking"
name = "Backwards-incompatible Changes"
showcontent = true
[[tool.towncrier.type]]
directory = "deprecation"
name = "Deprecations"
showcontent = true
[[tool.towncrier.type]]
directory = "change"
name = "Changes"
showcontent = true
[tool.mypy]
pretty = true
disallow_untyped_defs = true
check_untyped_defs = true