-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpyproject.toml
More file actions
102 lines (90 loc) · 3.98 KB
/
Copy pathpyproject.toml
File metadata and controls
102 lines (90 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# ============================================================================
# Canonical Python quality config — merge into your project's pyproject.toml.
#
# Source: a production Python codebase (ruff + mypy + pytest + coverage).
# De-repo-ified: project name, paths, and project-specific per-file-ignores
# removed. Replace YOUR_PACKAGE with your actual package name.
#
# Requires: Python >= 3.11, ruff, mypy, pytest, pytest-cov, pytest-socket,
# hypothesis, (optional: radon, xenon, pip-audit, pre-commit)
# ============================================================================
[project]
name = "YOUR_PACKAGE"
version = "0.1.0.dev0"
requires-python = ">=3.11"
[dependency-groups]
dev = [
"ruff>=0.9",
"mypy>=1.13",
"pytest>=8",
"pytest-cov>=6",
"pytest-socket>=0.7",
"hypothesis>=6",
"radon>=6",
"xenon>=0.9",
"pip-audit>=2.7",
"pre-commit>=4",
]
# ── ruff (lint + format) ────────────────────────────────────────────────────
[tool.ruff]
preview = true
src = ["src", "tests", "scripts"]
target-version = "py311"
line-length = 100
extend-exclude = ["project-plans", "dev-docs", "research"]
[tool.ruff.lint]
# Only activate preview rules that are explicitly listed in `select`.
# Prevents implicit activation of unstable rules on ruff updates.
explicit-preview-rules = true
select = [
"E", "W", "F", "I", "N", "UP", "B", "C4", "SIM", "PTH", "RUF",
"ANN", "S", "PL", "TID", "PT", "TRY", "DTZ",
]
[tool.ruff.lint.pylint]
# max-args intentionally exceeds the Rust template's 6: Python's first parameter
# (self/cls) counts toward the limit, so 8 Python args ≈ 7 in other languages.
max-args = 8
# max-statements counts only statements (not blank lines/comments), so it is
# not directly comparable to the TypeScript max-lines-per-function (80 lines).
max-statements = 100
max-locals = 20
max-nested-blocks = 5
max-bool-expr = 5
max-returns = 8
[tool.ruff.lint.mccabe]
# Cyclomatic complexity — set to 15 to match the TypeScript ESLint `complexity`
# threshold (both are cyclomatic complexity metrics) for cross-language parity.
max-complexity = 15
# Centrally-reviewable rule scoping (NOT inline escape hatches).
# `assert` (S101) and magic-value comparisons (PLR2004) are expected in tests.
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101", "PLR2004"]
# ── mypy (strict type checking) ─────────────────────────────────────────────
[tool.mypy]
strict = true
disallow_any_explicit = true
warn_unreachable = true
files = ["src", "tests", "scripts"]
# pydantic v2 model subclasses trip `--disallow-any-explicit` at the class
# definition (pydantic surfaces an inherited Any). If your project uses pydantic
# v2, uncomment this override and replace YOUR_PACKAGE.models with your model
# package path. Do NOT leave it active as a default if you don't use pydantic.
# [[tool.mypy.overrides]]
# module = ["YOUR_PACKAGE.models.*"]
# disable_error_code = ["explicit-any"]
# ── pytest ──────────────────────────────────────────────────────────────────
[tool.pytest.ini_options]
addopts = "--strict-markers --strict-config --disable-socket"
markers = [
"integration: end-to-end tests",
"property: hypothesis property-based tests",
"benchmark: performance benchmarks (non-blocking)",
"network: tests that exercise network adapters (must also use the enable_socket fixture)",
]
# ── coverage ────────────────────────────────────────────────────────────────
[tool.coverage.run]
branch = true
source = ["YOUR_PACKAGE"]
[tool.coverage.report]
fail_under = 80
exclude_lines = ["if TYPE_CHECKING:", "^\\s*\\.\\.\\.\\s*$"]