pyproject.toml (7888B)
1 # SPDX-License-Identifier: MIT 2 3 [build-system] 4 requires = ["hatchling", "hatch-vcs", "hatch-fancy-pypi-readme>=23.2.0"] 5 build-backend = "hatchling.build" 6 7 8 [project] 9 name = "attrs" 10 authors = [{ name = "Hynek Schlawack", email = "hs@ox.cx" }] 11 license = "MIT" 12 requires-python = ">=3.7" 13 description = "Classes Without Boilerplate" 14 keywords = ["class", "attribute", "boilerplate"] 15 classifiers = [ 16 "Development Status :: 5 - Production/Stable", 17 "License :: OSI Approved :: MIT License", 18 "Programming Language :: Python :: 3.7", 19 "Programming Language :: Python :: 3.8", 20 "Programming Language :: Python :: 3.9", 21 "Programming Language :: Python :: 3.10", 22 "Programming Language :: Python :: 3.11", 23 "Programming Language :: Python :: 3.12", 24 "Programming Language :: Python :: Implementation :: CPython", 25 "Programming Language :: Python :: Implementation :: PyPy", 26 "Typing :: Typed", 27 ] 28 dependencies = ["importlib_metadata;python_version<'3.8'"] 29 dynamic = ["version", "readme"] 30 31 [project.optional-dependencies] 32 tests-mypy = [ 33 'pytest-mypy-plugins; python_implementation == "CPython" and python_version >= "3.8"', 34 # Since the mypy error messages keep changing, we have to keep updating this 35 # pin. 36 'mypy>=1.6; python_implementation == "CPython" and python_version >= "3.8"', 37 ] 38 tests-no-zope = [ 39 # For regression test to ensure cloudpickle compat doesn't break. 40 'cloudpickle; python_implementation == "CPython"', 41 "hypothesis", 42 "pympler", 43 # 4.3.0 dropped last use of `convert` 44 "pytest>=4.3.0", 45 "pytest-xdist[psutil]", 46 "attrs[tests-mypy]", 47 ] 48 tests = ["attrs[tests-no-zope]", "zope.interface"] 49 cov = [ 50 "attrs[tests]", 51 # Ensure coverage is new enough for `source_pkgs`. 52 "coverage[toml]>=5.3", 53 ] 54 docs = [ 55 "furo", 56 "myst-parser", 57 "sphinx", 58 "zope.interface", 59 "sphinx-notfound-page", 60 "sphinxcontrib-towncrier", 61 "towncrier", 62 ] 63 dev = ["attrs[tests]", "pre-commit"] 64 65 [project.urls] 66 Documentation = "https://www.attrs.org/" 67 Changelog = "https://www.attrs.org/en/stable/changelog.html" 68 GitHub = "https://github.com/python-attrs/attrs" 69 Funding = "https://github.com/sponsors/hynek" 70 Tidelift = "https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi" 71 72 73 [tool.hatch.version] 74 source = "vcs" 75 raw-options = { local_scheme = "no-local-version" } 76 77 [tool.hatch.build.targets.wheel] 78 packages = ["src/attr", "src/attrs"] 79 80 [tool.hatch.metadata.hooks.fancy-pypi-readme] 81 content-type = "text/markdown" 82 83 # PyPI doesn't support the <picture> tag. 84 [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] 85 text = """<p align="center"> 86 <a href="https://www.attrs.org/"> 87 <img src="https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo.svg" width="35%" alt="attrs" /> 88 </a> 89 </p> 90 """ 91 92 [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] 93 path = "README.md" 94 start-after = "<!-- teaser-begin -->" 95 96 [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] 97 text = """ 98 99 ## Release Information 100 101 """ 102 103 [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] 104 path = "CHANGELOG.md" 105 pattern = "\n(###.+?\n)## " 106 107 [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] 108 text = """ 109 110 --- 111 112 [Full changelog](https://www.attrs.org/en/stable/changelog.html) 113 """ 114 115 # Point sponsor image URLs to versions. 116 [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] 117 pattern = '\/latest\/_static/sponsors' 118 replacement = '/$HFPR_VERSION/_static/sponsors' 119 120 121 [tool.pytest.ini_options] 122 addopts = ["-ra", "--strict-markers", "--strict-config"] 123 xfail_strict = true 124 testpaths = "tests" 125 filterwarnings = ["once::Warning", "ignore:::pympler[.*]"] 126 127 128 [tool.coverage.run] 129 parallel = true 130 branch = true 131 source_pkgs = ["attr", "attrs"] 132 133 [tool.coverage.paths] 134 source = ["src", ".tox/py*/**/site-packages"] 135 136 [tool.coverage.report] 137 show_missing = true 138 skip_covered = true 139 exclude_lines = [ 140 "pragma: no cover", 141 # PyPy is unacceptably slow under coverage. 142 "if PYPY:", 143 # not meant to be executed 144 ': \.\.\.$', 145 '^ +\.\.\.$', 146 ] 147 148 149 [tool.black] 150 line-length = 79 151 152 153 [tool.interrogate] 154 omit-covered-files = true 155 verbose = 2 156 fail-under = 100 157 whitelist-regex = ["test_.*"] 158 159 160 [tool.check-wheel-contents] 161 toplevel = ["attr", "attrs"] 162 163 164 [tool.ruff] 165 src = ["src", "tests", "conftest.py", "docs"] 166 167 select = ["ALL"] 168 ignore = [ 169 "A001", # shadowing is fine 170 "A002", # shadowing is fine 171 "A003", # shadowing is fine 172 "ANN", # Mypy is better at this 173 "ARG", # unused arguments are normal when implementing interfaces 174 "COM", # Black takes care of our commas 175 "D", # We prefer our own docstring style. 176 "E501", # leave line-length enforcement to Black 177 "FBT", # we don't hate bool args around here 178 "FIX", # Yes, we want XXX as a marker. 179 "PLR0913", # yes, many arguments, but most have defaults 180 "PLR2004", # numbers are sometimes fine 181 "SLF001", # private members are accessed by friendly functions 182 "TCH", # TYPE_CHECKING blocks break autodocs 183 "TD", # we don't follow other people's todo style 184 "C901", # we're complex software 185 "PLR0911", # we're complex software 186 "PLR0912", # we're complex software 187 "PLR0915", # we're complex software 188 "PGH001", # eval FTW 189 "S307", # eval FTW 190 "N807", # we need to create functions that start with __ 191 "ERA001", # we need to keep around some notes 192 "RSE102", # I like empty parens on raised exceptions 193 "N", # we need more naming freedom 194 "UP031", # format() is slow as molasses; % and f'' FTW. 195 "PD", # we're not pandas 196 "PLW0603", # sometimes we need globals 197 "TRY301", # I'm sorry, but this makes not sense for us. 198 ] 199 200 [tool.ruff.per-file-ignores] 201 "**/test_*" = [ 202 "ARG005", # we need stub lambdas 203 "S", 204 "SIM300", # Yoda rocks in asserts 205 "SIM201", # sometimes we need to check `not ==` 206 "SIM202", # sometimes we need to check `not ==` 207 "PT005", # we always add underscores and explicit names 208 "PT011", # broad is fine 209 "TRY", # exception best practices don't matter in tests 210 "EM101", # no need for exception msg hygiene in tests 211 "B904", # exception best practices don't matter in tests 212 "B015", # pointless comparison in tests aren't pointless 213 "B018", # pointless expressions in tests aren't pointless 214 "PLR0124", # pointless comparison in tests aren't pointless 215 "DTZ", # datetime best practices don't matter in tests 216 "UP037", # we test some older syntaxes on purpose 217 "B017", # pytest.raises(Exception) is fine 218 "PT012", # sometimes we need more than a single stmt 219 "RUF012", # we don't do ClassVar annotations in tests 220 ] 221 222 "conftest.py" = [ 223 "PT005", # we always add underscores and explicit names 224 ] 225 226 "src/*/*.pyi" = ["ALL"] # TODO 227 "tests/test_annotations.py" = ["FA100"] 228 "tests/typing_example.py" = [ 229 "E741", # ambiguous variable names don't matter in type checks 230 "B018", # useless expressions aren't useless in type checks 231 "B015", # pointless comparison in type checks aren't pointless 232 "TRY301", # exception hygiene isn't important in type checks 233 "UP037", # we test some older syntaxes on purpose 234 ] 235 236 [tool.ruff.isort] 237 lines-between-types = 1 238 lines-after-imports = 2 239 known-first-party = ["attr", "attrs"] 240 241 242 [tool.towncrier] 243 name = "attrs" 244 directory = "changelog.d" 245 filename = "CHANGELOG.md" 246 start_string = "<!-- towncrier release notes start -->\n" 247 template = "changelog.d/towncrier_template.md.jinja" 248 title_format = "" 249 issue_format = "[#{issue}](https://github.com/python-attrs/attrs/issues/{issue})" 250 underlines = ["", "", ""] 251 252 [[tool.towncrier.section]] 253 path = "" 254 255 [[tool.towncrier.type]] 256 directory = "breaking" 257 name = "Backwards-incompatible Changes" 258 showcontent = true 259 260 [[tool.towncrier.type]] 261 directory = "deprecation" 262 name = "Deprecations" 263 showcontent = true 264 265 [[tool.towncrier.type]] 266 directory = "change" 267 name = "Changes" 268 showcontent = true 269 270 271 [tool.mypy] 272 disallow_untyped_defs = true 273 check_untyped_defs = true