-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
186 lines (172 loc) · 7.38 KB
/
Copy pathpyproject.toml
File metadata and controls
186 lines (172 loc) · 7.38 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
[project]
name = "hnf1b-api"
version = "0.2.2"
description = "FastAPI-based REST API for managing clinical and genetic data for individuals with HNF1B disease"
requires-python = ">=3.10"
dependencies = [
# Core FastAPI dependencies
"email-validator>=2.3.0",
"fastapi>=0.116.1",
"pandas>=2.3.2",
"pwdlib[argon2,bcrypt]>=0.2.1", # Argon2id primary + bcrypt verifier fallback (Wave 5b Task 11)
"pydantic>=2.13.0",
"pydantic-settings>=2.14.2",
"pyjwt>=2.10.1",
"python-dotenv>=1.1.1",
"python-multipart>=0.0.27",
"uvicorn[standard]>=0.35.0",
# PostgreSQL and database dependencies
"sqlalchemy[asyncio]>=2.0.51",
"asyncpg>=0.29.0",
"alembic>=1.13.1",
"psycopg2-binary>=2.9.9",
# HTTP client
"requests>=2.31.0",
# Phenopackets and ontology dependencies
"phenopackets>=2.0.0", # GA4GH Phenopackets schema
"protobuf>=4.25.0", # For phenopackets serialization
"jsonschema>=4.20.0", # For phenopacket validation
"jsonpatch>=1.33", # For RFC 6902 JSON Patch (audit trail)
"pronto>=2.5.0", # For parsing OBO ontologies (HPO, MONDO)
"lxml>=6.1.0", # Pin transitive lxml above CVE-2026-41066 (XXE via iterparse/ETCompatXMLParser)
"jsonpath-ng>=1.6.0", # For complex JSON queries
"httpx>=0.28.1",
"aiohttp>=3.14.0",
"pyyaml>=6.0.2", # For config.yaml parsing
"redis>=5.0.0", # For distributed caching
"ga4gh.vrs>=2.1.3", # GA4GH VRS for proper variant digests (moved from phenopackets group for #56)
"scipy>=1.15.3",
"aiosmtplib>=5.1.0",
]
[dependency-groups]
dev = [
"ruff==0.16.1",
"mypy==2.3.0",
"types-jsonschema>=4.25.1.20250822",
"types-pyyaml>=6.0.12.20260408", # Type stubs for PyYAML
"types-redis>=4.6.0", # Type stubs for Redis
]
test = [
"ga4gh-vrs>=2.1.3",
"pytest==9.1.1",
"pytest-asyncio>=1.2.0", # Updated for pytest 8.x compatibility (0.21.1 incompatible)
"pytest-cov==7.1.0",
"pytest-xdist>=3.6.0", # Parallel test execution with per-worker DB isolation
"tqdm>=4.67.3",
"types-tqdm>=4.66.0", # Type stubs for tqdm
]
migration = [
"tqdm>=4.67.3", # Progress bars for migration
"rich>=13.7.0", # Rich console output
"deepdiff>=6.7.0", # For comparing data structures
]
phenopackets = [
"oaklib>=0.5.0", # Ontology Access Kit (optional)
]
[tool.mypy]
python_version = "3.10"
warn_return_any = false
warn_unused_configs = true
disallow_untyped_defs = false
no_implicit_optional = true
warn_unused_ignores = true
explicit_package_bases = true
[[tool.mypy.overrides]]
module = ["pandas.*", "scipy.*", "jsonpatch.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = ["ga4gh.*", "bioutils.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
# Optional embedding backend is not installed in CI. The embedding provider
# lazy-imports these behind a capability check, so missing stubs/imports must
# not fail typecheck.
module = ["sentence_transformers.*", "transformers.*"]
ignore_missing_imports = true
# NOTE: ga4gh.vrs and bioutils libraries do not include type annotations (no py.typed marker)
# and have no published type stubs on PyPI (verified 2025-01-06).
# These libraries are tested and functional; suppressing tool limitation only.
# TODO: Remove when upstream adds py.typed marker or type stubs become available.
[tool.ruff]
line-length = 88
target-version = "py310"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"D", # pydocstyle
]
ignore = [
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
"D203", # 1 blank line required before class docstring
"D213", # Multi-line docstring summary should start at the second line
]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.per-file-ignores]
# Alembic migration files: revision identifiers are required by Alembic framework
# These variables are read via introspection, not direct import
"alembic/versions/*.py" = ["F841", "E501", "D103", "D415"] # Unused variable, long SQL queries, Alembic funcs, docstring format
"alembic/env.py" = ["E501"] # Long comments explaining model imports
# Migration files: allow long SQL queries, data strings, and complex expressions
"migration/**/*.py" = ["E501"]
# Test files: allow long test strings and fixtures; test docstrings
# can be informal (D205 summary/description formatting, D301 escapes)
# D103: test functions don't need formal docstrings
"tests/*.py" = ["E501", "D103", "D205", "D301"]
# App files with SQL/JSONPath queries and long API parameters
"app/phenopackets/clinical_endpoints.py" = ["E501"] # JSONPath queries
"app/phenopackets/clinical_queries.py" = ["E501"] # JSONPath and SQL queries
"app/phenopackets/endpoints.py" = ["E501", "D417"] # SQL queries and API param descriptions
"app/phenopackets/routers/aggregations.py" = ["E501"] # Complex SQL queries with VEP classification
"app/phenopackets/routers/aggregations/survival/handlers/*.py" = ["E501", "D102"] # SQL query strings, concrete overrides of ABC methods
"app/phenopackets/validation/variant_validator.py" = ["E501"] # Long regex patterns
"app/phenopackets/variant_search_validation.py" = ["E501"] # Long comments
"app/core/patterns.py" = ["E501"] # Long regex patterns
"app/core/config.py" = ["E501"] # Long docstrings and examples
"app/publications/endpoints.py" = ["E501", "D106"] # Long strings and nested Config class
"app/services/ontology_service.py" = ["D107", "D205"] # __init__ docstrings and formatting
"app/schemas.py" = ["D101"] # Simple schema classes don't need docstrings
"examples/**/*.py" = ["E501"] # Example scripts with long print statements
[tool.ruff.lint.isort]
# Configuration compatible with black formatting
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
[tool.coverage.run]
# Trace lines that execute inside asyncio tasks. pytest-cov uses
# ``sys.settrace`` by default, which does not follow execution into event-loop
# workers reliably — async FastAPI route handlers tested via httpx's
# ASGITransport end up looking "uncovered" even when the tests clearly pass.
# Adding ``greenlet`` (used by SQLAlchemy's async bridge) and ``thread``
# ensures every execution path the test suite exercises gets counted.
concurrency = ["thread", "greenlet"]
[tool.coverage.report]
# Wave 6 Task 1: fail CI if overall coverage regresses below the gate.
# Today's baseline is ~70% (measured 2026-04-12 in CI parity run). The
# threshold is deliberately set at the current floor so any regression
# breaks the build; ratchet this upward in follow-on waves as component
# test coverage grows.
fail_under = 70
show_missing = true
skip_covered = false
# Lines that should not count against coverage — they represent code that
# cannot be executed directly (abstract method placeholders, type-checking
# guards, debug-only branches) or is already covered by explicit pragmas.
exclude_also = [
# Abstract method placeholders — concrete subclasses implement them;
# the `pass` body on the ABC itself is unreachable.
"^\\s*@(abc\\.)?abstractmethod",
# ``if TYPE_CHECKING:`` blocks never execute at runtime.
"if TYPE_CHECKING:",
# Defensive ``pass`` and ``...`` bodies on abstract members.
"^\\s*pass$",
"^\\s*\\.\\.\\.$",
# Raises that only fire as programmer-error guards, not normal flow.
"raise NotImplementedError",
# Main-module entrypoint guards.
"if __name__ == .__main__.:",
]