-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
257 lines (235 loc) · 8.62 KB
/
Copy pathpyproject.toml
File metadata and controls
257 lines (235 loc) · 8.62 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
[project]
name = "jero"
version = "0.1.1"
description = "An opinionated, msgspec-first ASGI micro-framework"
authors = [{ name = "Roger Thomas", email = "roger.thomas87@gmail.com" }]
readme = "README.md"
license = "MIT"
license-files = ["LICENSE"]
keywords = ["asgi", "msgspec", "web-framework", "rest", "api"]
requires-python = ">=3.13"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Software Development :: Libraries :: Application Frameworks",
"Framework :: AsyncIO",
"Typing :: Typed",
]
dependencies = ["msgspec>=0.21.1", "multipart>=1.0", "typing-extensions>=4.15"]
[project.optional-dependencies]
# `uv add "jero[granian]"` — jero plus the recommended ASGI server in one step.
granian = ["granian>=2.7"]
[project.urls]
Homepage = "https://RogerThomas.github.io/jero/"
Repository = "https://github.com/RogerThomas/jero"
Documentation = "https://RogerThomas.github.io/jero/"
[[tool.pyrefly.sub-config]]
matches = "tests"
[dependency-groups]
dev = [
"deptry>=0.24.0",
"mkdocstrings-python>=1.0.3",
"prek>=0.2.0",
"pylint>=4.0.4",
"pyright>=1.1.410",
"niquests>=3.19.1",
"pytest>=9.0.3",
"pytest-asyncio>=1.0.0",
"pytest-cov>=7.0.0",
"pytest-mock>=3.15.1",
"pytest-timeout>=2.4.0",
"ruff>=0.15.16",
"zensical>=0.0.26",
"pyrefly>=1.1.1",
"ty>=0.0.51",
"zuban>=0.8.2",
"mypy>=2.1.0",
"openai>=2.43.0",
"pydantic-settings>=2.14.2",
"openapi-spec-validator>=0.7.1",
"yeetr>=2026.7.1.post1",
]
[build-system]
requires = ["uv_build>=0.11.0,<0.13.0"]
build-backend = "uv_build"
[tool.uv.build-backend]
module-name = "jero"
module-root = ""
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["."]
# Default per-test timeout (seconds); a hung test fails instead of blocking the run.
# Override on a single test with @pytest.mark.timeout(N).
timeout = 1
# Async tests are marked with @pytest.mark.asyncio; each gets a fresh event loop.
asyncio_mode = "strict"
[tool.coverage.run]
branch = true
source = ["jero"]
[tool.coverage.report]
skip_empty = true
[tool.ruff]
target-version = "py313"
line-length = 100
# scratch_pad.py / tmp.py are throwaway sketches kept for reuse; exclude from all checks.
# force-exclude so they're skipped even when pre-commit passes the path explicitly.
extend-exclude = ["scratch_pad.py", "tmp.py"]
force-exclude = true
[tool.ruff.lint]
select = [
"A", # builtins shadowing
"ANN", # type annotations
"ARG", # unused arguments
"B", # bugbear (common bugs & bad patterns)
"BLE", # blind excepts
"C4", # comprehensions
"C90", # mccabe complexity
"COM", # commas
"DTZ", # datetime timezone
"E", # pycodestyle errors
"ERA", # eradicate commented-out code
"F", # pyflakes
"FA", # future annotations
"FBT", # boolean trap
"I", # import sorting
"ICN", # import conventions
"ISC", # implicit str concat
"N", # naming conventions
"NPY", # numpy rules
"PGH", # pygrep-hooks
"PT", # pytest style
"PTH", # pathlib
"RET", # return statements
"RUF", # Ruff extra rules
"S", # security
"SIM", # simplifications
"T10", # debugger statements
"TD", # TODOs must be annotated
"TID", # tidy imports
"TRY", # tryceratops
"UP", # pyupgrade / newer syntax
"W", # pycodestyle warnings
"YTT", # flake8-2020
]
ignore = [
"COM812", # trailing commas — conflicts with the ruff formatter
"D211", # no-blank-line-before-class
"D213", # multi-line-summary-second-line
"TC006", # allow unquoted types in typing.cast()
"TRY003", # long exception messages at raise sites
]
[tool.ruff.lint.per-file-ignores]
# The test client mirrors arbitrary user JSON payloads/responses — Any is intrinsic.
"jero/testing.py" = ["ANN401"]
# Tests assert (S101), and test handlers declare sources they don't read (ARG002);
# keep typing imports inline for readability (TC).
"tests/**" = ["S101", "TC001", "TC002", "TC003", "ARG002"]
# The demo app is jero application code: handler params, resource fields, and Struct
# fields are introspected at runtime, so their imports must stay runtime (not TC-gated).
"demo_app/**" = ["TC001", "TC002", "TC003"]
# Self-contained PEP 723 benchmark script (rendered into the performance docs). It's
# deliberately kept simple rather than annotated to a library standard: loose annotations
# (ANN), an assert per response (S101), a bool flag (FBT), a × / µ output table
# (RUF001/RUF003), and a commented column legend (ERA001). ruff-format and every other
# rule still apply.
"benchmarks/micro_bench.py" = [
"ANN",
"S101",
"FBT",
"RUF001",
"RUF003",
"ERA001",
]
[tool.pyright]
# Target the minimum supported version so 3.14-only APIs are caught as errors.
pythonVersion = "3.13"
typeCheckingMode = "strict"
# Pin the uv-managed venv so pyright resolves imports even when it's launched
# outside `uv run` (e.g. an editor/LSP). Without this it can't find jero's deps
# and emits spurious "unknown import symbol" errors the CLI run never sees.
venvPath = "."
venv = "./.venv"
exclude = ["./.venv", "scratch_pad.py", "tmp.py", "benchmarks/micro_bench.py"]
# pytest fixtures use the `_name`-function + `@pytest.fixture(name=...)` pattern, so
# they read as unused to pyright (pytest injects them by string). Disable the check
# under tests/ only; jero/ stays strict so genuinely dead functions are still caught.
[[tool.pyright.executionEnvironments]]
root = "tests"
extraPaths = ["."]
reportUnusedFunction = "none"
[tool.ty.rules]
# mypy/pyright/zuban still need blanket `type: ignore` on lines where pydantic-settings
# populates fields from the environment; ty no longer does, so silence its complaint.
unused-type-ignore-comment = "ignore"
[tool.deptry]
# The demo app is dev/docs-only example code (not shipped) and uses dev dependencies
# like niquests, so it isn't scanned for the package's dependency contract; error.py is
# the throwaway error-design playground (rich, self-imports jero). micro_bench.py is a
# self-contained PEP 723 script: its deps (fastapi, litestar, blacksheep, …) are declared
# inline for `uv run`, not in the package contract.
extend_exclude = [
'scratch_pad\.py',
'tmp\.py',
'demo_app/',
'error\.py',
'benchmarks/micro_bench\.py',
]
[tool.deptry.per_rule_ignores]
# granian is the server extra (`jero[granian]`): a CLI users run, never an import.
DEP002 = ["granian"]
[tool.pylint.main]
# Throwaway sketches kept for reuse; don't lint them. micro_bench.py is a self-contained
# PEP 723 script: it imports uninstalled competitor frameworks (import-error) lazily
# inside each builder (import-outside-toplevel, intentional for graceful skip-if-absent).
ignore-paths = [
'.*scratch_pad\.py$',
'.*tmp\.py$',
'.*benchmarks/micro_bench\.py$',
]
disable = [
"R0902",
"R0903",
"R0911",
"R0912",
"R0913",
"R0914",
# duplicate-code is noisy across tests that share a setup shape (e.g. posting a
# widget through the client) — the similarity is intentional, not a refactor signal.
"R0801",
# the `multipart` package ships no type stubs, so pylint can't see its
# members — these are false positives (pyright already ignores them at source).
"E1101", # no-member
"E1123", # unexpected-keyword-arg
"E1133", # not-an-iterable
# ruff owns line length (line-length = 100); don't double-report it here.
"C0301", # line-too-long
]
[tool.pylint.basic]
# Throwaway sketches/demo (kept for reuse, or to be deleted) — don't scan their imports.
# jero uses descriptive PascalCase / single-cap TypeVars (THeaders, TUser, FactoryT).
typevar-rgx = "^_?[A-Z][a-zA-Z0-9]*$"
[tool.pylint.design]
# R0913 (too-many-arguments) is disabled outright above; this is its newer sibling
# (positional-specific), raised so internal fast-path helpers (e.g. _Binder._one/_finish)
# can take several positional args without a lint failure.
max-positional-arguments = 10
[tool.pylint.format]
max-module-lines = 5000
[tool.pyrefly]
# micro_bench.py imports competitor frameworks that aren't project deps (they're PEP 723
# inline deps resolved by `uv run`), so type-checking it here only yields missing-imports.
project-excludes = [
"./.venv",
"scratch_pad.py",
"tmp.py",
"benchmarks/micro_bench.py",
]
# Target the minimum supported version so 3.14-only APIs are caught as errors.
python-version = "3.13.0"
infer-with-first-use = false