-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
186 lines (167 loc) · 6.58 KB
/
Copy pathpyproject.toml
File metadata and controls
186 lines (167 loc) · 6.58 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
[build-system]
requires = ["hatchling==1.27.0"]
build-backend = "hatchling.build"
[project]
name = "idea2strategy-backtest-engine"
version = "0.1.0"
description = "Reproducible server-side backtest API and worker for Idea2Strategy."
requires-python = ">=3.12,<3.13"
dependencies = [
"boto3>=1.40,<2.0",
"fastapi==0.141.1",
"jsonschema>=4.23,<5.0",
# Runtime, not test-only: `attempt_coordinator.ProcessResourceMonitor` samples CPU and
# memory through psutil to enforce the D29 compute limits. While this sat in the `test`
# extra a real deployment could not enforce a limit at all.
"psutil==7.2.2",
"psycopg[binary]>=3.2,<4.0",
"pyarrow==25.0.0",
"sqlalchemy>=2.0,<3.0",
"tzdata==2026.3",
"uvicorn==0.52.1",
]
[project.optional-dependencies]
# `httpx` (not the non-existent `httpx2`) is what starlette.testclient imports.
test = [
"freezegun==1.5.5",
"httpx==0.28.1",
"psutil==7.2.2",
"pytest==9.1.1",
"pytest-cov==7.1.0",
# A hang must name the test that hung. Without this, CI's job timeout kills a
# block-buffered pytest and the log contains no test name at all.
"pytest-timeout==2.4.0",
"testcontainers[postgres]==4.15.0",
]
dev = [
"idea2strategy-backtest-engine[test]",
"mypy==2.3.0",
"ruff==0.16.1",
# Stubs, not runtime dependencies: without these mypy reports the import itself
# as an error and the module's real type errors stay hidden behind it.
"types-jsonschema==4.26.0.20260518",
]
[project.scripts]
backtest-api = "backtest_engine.api:run"
backtest-worker = "backtest_engine.worker:run"
backtest-validate-deployment-artifacts = "backtest_engine.deployment_artifacts:run"
[tool.hatch.build.targets.wheel]
packages = ["src/backtest_engine"]
[tool.pytest.ini_options]
# The default run is the fast, Docker-free unit suite. `-m docker` on the command
# line overrides this marker expression and selects the Testcontainers suite.
addopts = "-q -m 'not docker'"
pythonpath = ["src"]
testpaths = ["tests"]
markers = [
"docker: integration test requiring a running Docker daemon (Testcontainers PostgreSQL 16).",
]
[tool.coverage.run]
branch = true
source = ["backtest_engine"]
[tool.ruff]
line-length = 120
target-version = "py312"
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"PIE", # flake8-pie
"PTH", # flake8-use-pathlib
"RET", # flake8-return
"RUF", # ruff-specific
"SIM", # flake8-simplify
"TID", # flake8-tidy-imports
"UP", # pyupgrade
"W", # pycodestyle warnings
]
ignore = [
# `timezone.utc` is the spelling used consistently across both D repositories and
# the sibling data-pipeline. UP017 would rewrite 29 lines in modules owned by other
# rebuild cards purely for an alias.
"UP017",
# `class X(str, Enum)` is load-bearing here: several of these enums are serialised
# into reproducibility hashes and `StrEnum` changes `__str__`/`__format__` behaviour.
# Migrating them is a behaviour change that belongs to the card that owns the module.
"UP042",
# Class-level tuples/frozensets used as immutable lookup tables are intentional and
# are never mutated; `ClassVar` annotations would add noise without adding safety.
"RUF012",
# `pytest.raises(match=...)` patterns in the existing suite use plain prose; making
# every one of them an anchored regex is a test-cleanup task (BT7), not a lint gate.
"RUF043",
# An assignment immediately before `return` is frequently the clearest way to name an
# intermediate value in the SQL-building code below.
"RET504",
# SIM300 reads `assert MONEY_QUANTUM == Decimal("0.00000001")` as a Yoda condition and
# proposes flipping it to `Decimal(...) == MONEY_QUANTUM`, which is the actual Yoda
# form. The rule's heuristic misfires on SCREAMING_CASE constants, which this codebase
# uses heavily for pinned canonical values.
"SIM300",
]
[tool.ruff.lint.isort]
lines-after-imports = 2
known-first-party = ["backtest_engine", "d_market_data_testkit", "d_reproducibility_testkit"]
[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "parents"
[tool.ruff.lint.per-file-ignores]
# Pre-existing violations in modules that belong to other rebuild cards (BT1/BT4/BT6).
# These are scoped to one file and one rule each so a fix removes the entry; they are
# not repository-wide suppressions. Every entry is reported back for the owning card.
"src/backtest_engine/__init__.py" = ["I001", "RUF022"]
"src/backtest_engine/execution_model.py" = ["I001", "B905"]
"src/backtest_engine/result_query.py" = ["SIM102"]
"tests/test_monthly_judgment.py" = ["E501"]
[tool.mypy]
python_version = "3.12"
files = ["src/backtest_engine", "tests/conftest.py", "tests/persistence"]
namespace_packages = true
explicit_package_bases = true
mypy_path = ["src", "tests"]
check_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true
warn_no_return = true
strict_equality = true
# The pre-canonical test modules are rewritten wholesale in BT7; typing them now would
# be churn. `tests/persistence` and `tests/conftest.py` are checked above.
[[tool.mypy.overrides]]
# The persistence layer is new code and is held to full strictness.
module = ["backtest_engine.persistence.*", "conftest", "persistence.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_calls = true
disallow_any_generics = true
warn_return_any = true
no_implicit_reexport = true
[[tool.mypy.overrides]]
# Legacy modules that no rebuild card currently owns. Each entry disables exactly the
# error code that module still trips, so the suppression cannot hide a new class of
# defect, and each is reported back as an open item.
module = ["backtest_engine.market_data"]
disable_error_code = ["union-attr"]
[[tool.mypy.overrides]]
module = ["backtest_engine.result_snapshot"]
disable_error_code = ["arg-type"]
[[tool.mypy.overrides]]
module = ["backtest_engine.detail_object_manifest"]
disable_error_code = ["attr-defined"]
[[tool.mypy.overrides]]
# Third-party packages that ship no type information. Not a suppression of our own
# errors: mypy simply has nothing to check these imports against.
module = ["boto3.*", "docker.*", "pyarrow.*", "testcontainers.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
# In-flight modules owned by BT1 (contracts/lifecycle rewrite). Each entry names the
# single error code that module currently trips; delete the entry when BT1 lands.
module = ["backtest_engine.contracts"]
disable_error_code = ["union-attr"]
[[tool.mypy.overrides]]
module = ["backtest_engine.lifecycle"]
disable_error_code = ["assignment"]