Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
341 lines (323 loc) · 15.4 KB
/
Copy pathpyproject.toml
File metadata and controls
341 lines (323 loc) · 15.4 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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
[project]
name = "monty-workspace"
version = "0"
requires-python = ">=3.10"
[tool.uv.workspace]
members = ["crates/monty-python", "crates/monty-runtime", "packages/pydantic-monty"]
[dependency-groups]
dev = [
"basedpyright>=1.34.0",
"maturin>=1.15.0,<2.0",
"mypy>=2.1.0",
"ruff>=0.14.7",
# markdown formatting (`make format-md`); style is in .mdformat.toml
"mdformat>=0.7.22",
"mdformat-tables>=1.0.0",
"mdformat-mkdocs>=5.2.1",
"mdformat-frontmatter>=2.1.2",
"httpx2>=2.12.0",
"websockets>=14",
]
# used only by `examples/`; opt in with `uv run --group examples ...`, `make dev-py` skips it, `make lint-py` needs it
examples = [
"duckdb>=1.0.0",
"openpyxl>=3.1.5",
"pillow>=11.0.0",
"types-openpyxl>=3.1.5",
"playwright>=1.58.0",
"beautifulsoup4>=4.14.3",
"logfire>=4.25.0",
"pydantic-ai-slim[anthropic,openai]>=1.63.0",
]
build = [
"twine>=6.1.0",
]
docs = [
"mkdocs>=1.6.1",
"mkdocs-material>=9.7.7",
"mkdocstrings[python]>=0.30",
]
# https://beta.ruff.rs/docs/configuration/
[tool.ruff]
line-length = 120
include = [
"scripts/**/*.py",
"crates/**/*.py",
"crates/**/*.pyi",
]
# Exclude files with intentional syntax errors or special formatting requirements
extend-exclude = [
"crates/monty-bench/benches/python",
"crates/monty/test_cases/function__err_duplicate_param.py",
"crates/monty/test_cases/function__err_repeated_keyword.py",
"crates/monty/test_cases/nonlocal__error_module_level.py",
"crates/monty/test_cases/traceback__nonlocal_module_scope.py",
# invalid `match` patterns whose compile-time SyntaxError is the point of the test
"crates/monty/test_cases/match__error_as_duplicate.py",
"crates/monty/test_cases/match__error_capture_unreachable.py",
"crates/monty/test_cases/match__error_different_names.py",
"crates/monty/test_cases/match__error_duplicate_key.py",
"crates/monty/test_cases/match__error_duplicate_complex_key.py",
"crates/monty/test_cases/match__error_duplicate_binary_complex_key.py",
"crates/monty/test_cases/match__error_duplicate_bigint_key.py",
"crates/monty/test_cases/match__error_duplicate_zero_key.py",
"crates/monty/test_cases/match__error_duplicate_int_key.py",
"crates/monty/test_cases/match__error_duplicate_name.py",
"crates/monty/test_cases/match__error_multiple_stars.py",
"crates/monty/test_cases/match__error_or_wildcard_unreachable.py",
"crates/monty/test_cases/match__error_repeated_attr.py",
"crates/monty/test_cases/match__error_wildcard_unreachable.py",
# These files test specific quote styles in error messages and must not be reformatted
"crates/monty/test_cases/type__float_repr_newline.py",
"crates/monty/test_cases/type__float_repr_both_quotes.py",
# Irregular spacing in the `class` header is the point of the test — locating
# the `class` keyword must not depend on it being exactly one space
"crates/monty/test_cases/decorator__class_body_traceback.py",
]
[tool.uv]
# this is a monorepo without a root package
package = false
# https://docs.astral.sh/uv/reference/settings/#exclude-newer
# make sure to use relative durations:
exclude-newer = "7 days"
# Apply CA distrust updates immediately (CVE-2026-111943).
exclude-newer-package = { certifi = "0 days" }
[tool.ruff.lint]
extend-select = [
"Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q
"RUF100", # https://docs.astral.sh/ruff/rules/unused-noqa/
"I", # https://docs.astral.sh/ruff/rules/#isort-i
"FA", # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa
]
flake8-quotes = { inline-quotes = "single", multiline-quotes = "double" }
mccabe = { max-complexity = 14 }
[tool.ruff.lint.isort]
combine-as-imports = true
known-first-party = ["pydantic_monty"]
# stdlib since 3.11, which the 3.10 floor hides from ruff's classification
extra-standard-library = ["tomllib"]
[tool.ruff.lint.per-file-ignores]
"crates/monty/test_cases/{str,bytes}__percent_format.py" = [
"F504", # unused mapping key - tests that a mapping operand never reports leftovers
"F506", # mixed positional and named placeholders - tests CPython's argument consumption order
"F507", # placeholder/argument count mismatch - the point of the argument-count tests
]
"crates/monty/test_cases/import__future_{late,nested}.py" = [
"F404", # late `__future__` import - the SyntaxError these cases expect
]
"crates/monty/test_cases/*.py" = [
"E722", # bare except - needed for testing try/except with bare except clauses
"E711", # Comparison to `None` should be `cond is None`
"E712", # Comparison to True/False - needed for testing boolean behavior
"E714", # Test for object identity should be `is not`
"E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks
"E731", # Do not assign a lambda expression, use a def - needed for testing lambda expressions
"F541", # f-string without any placeholders
"F601", # duplicate dict literal key - tests duplicate-key replacement behavior
"F622", # two starred expressions in one assignment - the SyntaxError under test
"F632", # ignore replace `is` with `==` - we have lots of these tests
"F701", # break outside loop - needed for testing break error handling
"F702", # continue not properly in loop - needed for testing continue error handling
"F704", # await outside function - needed for testing top-level async/await
"F811", # Redefinition of unused variable
"F821", # traceback undefined call test intentionally uses undefined name
"F823", # chained-assign test intentionally reads a local before its first assignment
"F841", # unused variable - needed for testing exception variable cleanup
"F401", # Intentionally imports unknown typing constructs to test silent ignore behavior
"F403", # star import test intentionally uses `from sys import *`
"F407", # unknown `__future__` feature - the point of the test is that it's a SyntaxError
"E402", # Typing test file has multiple import sections to test different import patterns
"E401", # Multiple imports on one line - needed for testing `import a, b` syntax
"I001", # Import block unsorted - needed for testing `import a, b` syntax
]
"crates/monty/test_cases/class__annotations_future.py" = [
# Scoped to this file so the single-quote convention stays enforced across
# the other test cases: these tests exist to prove that double-quoted
# annotations normalize to single quotes exactly as CPython's does.
"Q000", # double quotes are the subject of the test, not a style slip
"F722", # `e: "it's"` is a string literal under test, not a forward reference
]
"crates/monty-typeshed/vendor/typeshed/stdlib/**/*.pyi" = [
"F403", # unable to detect undefined names
"F821", # Undefined name
]
# Monty's narrowed replacement stubs keep upstream typeshed's structure verbatim
# (e.g. the `from _collections_abc import *` fallback branch), so mirror the
# vendored exemptions rather than diverging from upstream.
"crates/monty-typeshed/custom/**/*.pyi" = [
"F403", # unable to detect undefined names
"F821", # Undefined name
]
"crates/monty-type-checking/tests/good_types.py" = [
"F704", # await outside function - needed for testing top-level async/await
]
"crates/monty-type-checking/tests/bad_types.py" = [
"E402", # an import next to its cases keeps the earlier line numbers in the snapshot unchanged
]
[tool.ruff.format]
docstring-code-format = true
quote-style = "single"
[tool.pyright]
pythonVersion = "3.14"
typeCheckingMode = "strict"
reportUnnecessaryTypeIgnoreComment = true
include = ["scripts", "crates/monty/test_cases", "crates/monty-python", "crates/monty-type-checking", "examples"]
exclude = [
"crates/monty-type-checking/tests/bad_types.py",
"crates/monty-type-checking/tests/reveal_types.py",
# duplicate parameter name test intentionally has a syntax error
"crates/monty/test_cases/function__err_duplicate_param.py",
# repeated keyword argument test intentionally has a syntax error
"crates/monty/test_cases/function__err_repeated_keyword.py",
# annotation quote-normalization test: `e: "it's"` is a string literal under
# test, which pyright reads as a malformed forward reference
"crates/monty/test_cases/class__annotations_future.py",
# `__annotate__` and the argument errors of typing forms (`Annotated[int]`,
# `ClassVar[int, str]`, `Any[int]`) are the behaviour under test
"crates/monty/test_cases/function__annotations.py",
"crates/monty/test_cases/typing__special_forms.py",
# annotations that are not type expressions (`x: 1`, a string naming a
# variable, bare generics) are evaluated by `get_type_hints` under test
"crates/monty/test_cases/typing__get_type_hints.py",
"crates/monty/test_cases/typing__get_type_hints_classes.py",
"crates/monty/test_cases/typing__get_type_hints_dataclasses.py",
"crates/monty/test_cases/typing__get_type_hints_functions.py",
"crates/monty/test_cases/typing__get_type_hints_formats.py",
"crates/monty/test_cases/typing__get_type_hints_future.py",
"crates/monty/test_cases/annotationlib__forward_ref.py",
# `break`/`return`/`continue` exiting a `finally` block (PEP 765) is the
# behavior under test; basedpyright rejects it unconditionally
"crates/monty/test_cases/async__control_flow.py",
"crates/monty/test_cases/refcount__finally_swallow.py",
"crates/monty/test_cases/try_finally__control_flow.py",
# break/continue outside loop tests intentionally test error handling
"crates/monty/test_cases/loop__break_outside_error.py",
"crates/monty/test_cases/loop__continue_outside_error.py",
"crates/monty/test_cases/loop__break_in_function_error.py",
"crates/monty/test_cases/loop__continue_in_function_error.py",
"crates/monty/test_cases/loop__break_in_if_error.py",
"crates/monty/test_cases/loop__continue_in_if_error.py",
# invalid `match` patterns whose compile-time SyntaxError is the point of the test
"crates/monty/test_cases/match__error_as_duplicate.py",
"crates/monty/test_cases/match__error_capture_unreachable.py",
"crates/monty/test_cases/match__error_different_names.py",
"crates/monty/test_cases/match__error_duplicate_key.py",
"crates/monty/test_cases/match__error_duplicate_complex_key.py",
"crates/monty/test_cases/match__error_duplicate_binary_complex_key.py",
"crates/monty/test_cases/match__error_duplicate_bigint_key.py",
"crates/monty/test_cases/match__error_duplicate_zero_key.py",
"crates/monty/test_cases/match__error_duplicate_int_key.py",
"crates/monty/test_cases/match__error_duplicate_name.py",
"crates/monty/test_cases/match__error_multiple_stars.py",
"crates/monty/test_cases/match__error_or_wildcard_unreachable.py",
"crates/monty/test_cases/match__error_repeated_attr.py",
"crates/monty/test_cases/match__error_wildcard_unreachable.py",
# deliberately calls `reduce`/`partial` with wrong arity and types to pin
# their TypeError messages
"crates/monty/test_cases/functools__reduce.py",
"crates/monty/test_cases/functools__partial.py",
# deliberately subscripts types with the wrong arity and with non-type
# arguments to pin `types.GenericAlias` behaviour
"crates/monty/test_cases/generic_alias.py",
"crates/monty/test_cases/generic_alias__not_subscriptable.py",
"crates/monty/test_cases/refcount__generic_alias.py",
"crates/monty/test_cases/typing__union.py",
"crates/monty/test_cases/refcount__typing_union.py",
"scripts/startup_performance.py",
"examples/web_scraper/example_code.py",
# two starred targets in one assignment is the SyntaxError under test
"crates/monty/test_cases/unpack__err_multiple_starred.py",
]
venv = ".venv"
# sandbox-side code copied verbatim from the PyScript example: `pydom`, `DOMParser`,
# `open_url`, `set_interval` and `random` are bound by the host, not imported, and
# the upstream file has no annotations; every other strict rule still applies
[[tool.pyright.executionEnvironments]]
root = "examples/antigravity"
reportUndefinedVariable = false
reportMissingParameterType = false
reportUnknownParameterType = false
reportUnknownMemberType = false
reportUnknownVariableType = false
# we include tests cases in type checking then switch off all rules that break
# so the files don't show as errors in the IDE
[[tool.pyright.executionEnvironments]]
root = "crates/monty/test_cases"
reportUnusedExpression = false
reportOperatorIssue = false
reportGeneralTypeIssues = false
reportMissingImports = false
reportUnknownMemberType = false
reportUnnecessaryComparison = false
reportUnnecessaryIsInstance = false
reportUnknownArgumentType = false
reportUnknownVariableType = false
reportUnhashable = false
reportCallIssue = false
reportUnknownParameterType = false
reportMissingParameterType = false
reportUnknownLambdaType = false
reportArgumentType = false
# iter mode tests use external functions defined in the test runner
reportUndefinedVariable = false
# loop variable persistence tests have "possibly unbound" variables
reportPossiblyUnboundVariable = false
# exception variable cleanup tests intentionally access unbound variables
reportUnboundVariable = false
# attribute error tests intentionally access/assign non-existent attributes
reportAttributeAccessIssue = false
# decorator tests deliberately use untyped decorators (incl. bare lambdas)
reportUntypedClassDecorator = false
reportUntypedFunctionDecorator = false
# `match` tests deliberately include subjects no case matches
reportMatchNotExhaustive = false
# unused variables, classes, functions and imports are fine in test cases —
# e.g. the walrus-in-decorator tests decorate a throwaway `def f(): pass`, the
# same way the class-side ones decorate a throwaway `class C: pass`
reportUnusedVariable = false
reportUnusedClass = false
reportUnusedFunction = false
reportUnusedImport = false
reportDuplicateImport = false
reportAssignmentType = false
reportFunctionMemberAccess = false
# ~bool is deprecated in Python 3.16 but valid in 3.14
reportDeprecated = false
# star import test intentionally uses `from sys import *`
reportWildcardImportFromLibrary = false
# some test cases intentionally exercise invalid index assignment/runtime error paths
reportIndexIssue = false
# dunder tests intentionally return the wrong type (e.g. `__repr__` returning int)
reportIncompatibleMethodOverride = false
# collections.namedtuple factory tests use the functional form, not class-based NamedTuple
reportUntypedNamedTuple = false
# `break`/`return`/`continue` inside `with` tests bind through Optional outer
# variables that pyright can't narrow.
reportOptionalMemberAccess = false
[[tool.pyright.executionEnvironments]]
root = "crates/monty-type-checking"
reportUnnecessaryIsInstance = false
# mypy is only used by `mypy.stubtest` (see Makefile `lint-py`); these settings
# keep it from traversing the whole monorepo when building the stub graph.
[tool.mypy]
files = ["crates/monty-python/python/pydantic_monty"]
exclude = [
"crates/monty-typeshed/",
"crates/monty/test_cases/",
"crates/monty-type-checking/",
"examples/",
"playground/",
"target/",
]
[tool.codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
ignore-words-list = 'crate,NotIn,ser,IST,Nd,afterAll,beforeAll,deques,wit'
skip = [
"Cargo.lock",
"crates/monty-js/package-lock.json",
"crates/monty-bench/benches/python/pyperformance_*.py",
"crates/monty-typeshed/vendor/typeshed/stdlib/*",
"crates/monty/src/types/str.rs",
]
[tool.inline-snapshot]
format-command="ruff format --stdin-filename {filename}"