-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
165 lines (155 loc) · 5.83 KB
/
Copy pathpyproject.toml
File metadata and controls
165 lines (155 loc) · 5.83 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
# pyproject.toml
[project]
name = "kurrentschrift"
version = "0.28.0"
description = "Analysis-by-synthesis ductus-template extraction and re-inking for normed pre-1900 German Kurrent script."
authors = [{ name = "Markus Neusinger", email = "admin@kurrentschrift.ink" }]
readme = "README.md"
license = "MIT"
requires-python = ">=3.13"
keywords = [
"kurrent",
"paleography",
"german-cursive",
"historical-handwriting",
"handwriting-synthesis",
"analysis-by-synthesis",
"ductus",
]
# Trove classifiers: the project is not published to PyPI, but these are what
# GitHub, `uv`/pip metadata readers and the CITATION.cff consumers show for it,
# and they were missing entirely. `Private :: Do Not Upload` is the documented
# guard against an accidental upload.
classifiers = [
"Private :: Do Not Upload",
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
# No `License ::` classifier: PEP 639 forbids pairing one with the SPDX
# `license = "MIT"` expression above, and modern backends reject the mix.
"Natural Language :: German",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.13",
"Topic :: Scientific/Engineering :: Image Processing",
"Topic :: Text Processing :: Linguistic",
"Typing :: Typed",
]
dependencies = [
# Scientific stack — ductus extraction, distance transform, skeletonisation
"numpy>=2.5.1",
"scipy>=1.18.0",
"scikit-image>=0.24",
"pillow>=12.3.0",
# API
"fastapi>=0.141.1",
"uvicorn[standard]>=0.52.1",
"pydantic>=2.10",
"pydantic-settings>=2.15.0",
"python-dotenv>=1.0.0",
# Admin auth — Cloudflare Access JWT verification against the team JWKS.
"pyjwt[crypto]>=2.13.0",
# Database — Postgres (Cloud SQL on the anyplot instance for now)
"sqlalchemy[asyncio]>=2.0.52",
"asyncpg>=0.30.0",
"pg8000>=1.31.0",
"alembic>=1.19.0",
"cloud-sql-python-connector[asyncpg,pg8000]>=1.21.0",
"shapely>=2.1.2",
"orjson>=3.11.9",
"httpx>=0.28.1",
]
[project.optional-dependencies]
# Visualisation for the dev inspection tools (tools/glyphlab). Kept OUT of the
# runtime `dependencies` so it never enters the Cloud Run image — only dev/test.
viz = [
"matplotlib>=3.11.1",
]
dev = [
"ruff>=0.16.1",
# Type stubs for the numpy/scipy-heavy core (dev-only — never in the runtime image).
"scipy-stubs~=1.18.0",
"kurrentschrift[viz]",
]
test = [
"pytest>=9.1.1",
"pytest-asyncio>=1.4.0",
"pytest-cov>=5",
"aiosqlite>=0.20",
"kurrentschrift[viz]",
]
[project.urls]
Homepage = "https://kurrentschrift.ink"
Repository = "https://github.com/MarkusNeusinger/kurrentschrift"
Documentation = "https://github.com/MarkusNeusinger/kurrentschrift/blob/main/docs/index.md"
Changelog = "https://github.com/MarkusNeusinger/kurrentschrift/blob/main/CHANGELOG.md"
Issues = "https://github.com/MarkusNeusinger/kurrentschrift/issues"
# ===== Ruff Configuration =====
[tool.ruff]
line-length = 120
exclude = [
".git",
".venv",
"__pycache__",
"dist",
# Ruff >=0.16 also formats Python code blocks inside Markdown. The docs are
# prose whose snippets are illustrative — schema sketches, pseudo-code and
# aligned trailing comments that carry meaning. They are documentation, not
# source, and must not be reflowed by the formatter.
"*.md",
]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"W", # pycodestyle warnings
"I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
"UP007", # pyupgrade: use X | Y instead of Optional[X] / Union[X, Y]
"UP045", # pyupgrade: use X | None instead of Optional[X]
]
ignore = [
"E501", # Line too long (formatter handles where sensible)
"C901", # Too complex
]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "auto"
skip-magic-trailing-comma = true
[tool.ruff.lint.isort]
force-single-line = false
lines-after-imports = 2
known-first-party = ["core", "api"]
split-on-trailing-comma = false
[tool.ruff.lint.flake8-bugbear]
# FastAPI's dependency-injection markers are designed to be evaluated once in
# argument defaults — the idiomatic pattern, not a B008 mutable-default bug.
extend-immutable-calls = ["fastapi.Depends", "fastapi.Header"]
# ===== Pytest =====
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = ["--strict-markers", "-ra"]
filterwarnings = [
# Deprecations from OUR code fail loudly instead of accumulating as noise
# (the 422-constant rename sat unnoticed behind 9 warnings). Third-party
# deprecations stay warnings — we can't fix those here. The module regex
# is start-anchored by re.match; the (\.|$) boundary stops prefix
# collisions with third-party packages like `apischema` or `corenlp`.
'error::DeprecationWarning:api(\.|$)',
'error::DeprecationWarning:core(\.|$)',
'error::DeprecationWarning:tools(\.|$)',
# …and one rule that depends on neither the module NOR the category.
# Starlette warns about its own renamed status constants with
# `stacklevel=3`, so Python blames the frame three levels up —
# `fastapi.routing`, never `api.*` — and the three module-anchored rules
# above look straight past it. That is how five deprecated constants (four
# HTTP_422_UNPROCESSABLE_ENTITY, one HTTP_413_REQUEST_ENTITY_TOO_LARGE) sat
# in the error paths until the 2026-09-02 audit counted them. No category
# either (so: any Warning), because starlette 1.6 moved the warning off
# DeprecationWarning onto its own UserWarning subclass — a category-pinned
# rule would have gone blind again at the next upgrade. Whoever the
# traceback blames and whatever the class, a renamed `HTTP_*` constant is
# OUR call site: fail the run.
'error:.*is deprecated\. Use .HTTP_',
]