-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpyproject.toml
More file actions
218 lines (203 loc) · 11.2 KB
/
Copy pathpyproject.toml
File metadata and controls
218 lines (203 loc) · 11.2 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
[project]
name = "keel-trader"
version = "0.11.2"
description = "Offline-first, broker-agnostic, rule-based spot-trading agent (halal policy by default)"
license = "Apache-2.0"
readme = "README.md"
authors = [
{ name = "CodeGate Software" }
]
requires-python = ">=3.11"
dependencies = [
"click>=8.4.2",
# pyyaml/python-dotenv are deliberately NOT listed here: nothing under `keel/` imports
# them any more (config parsing and secret loading both moved into keel-core), so they
# arrive transitively via the `keel-core` dependency below. Re-add them here only if
# `keel/` starts importing them directly again.
# ⚠️ The workspace siblings are pinned `==` to this exact version, and every workspace
# pyproject does the same. Unpinned, an ALREADY-INSTALLED older sibling satisfies the
# requirement, so installing the new `keel_trader` wheel upgrades nothing else and leaves a
# deployment running new code against old libraries -- `~/keel` ran `keel-trader 0.5.7`
# against `keel-core 0.5.5` for two releases exactly that way. These are not third-party
# dependencies with independent release cycles: they are cut from this repo, at this version,
# in one build, so `==` states a fact rather than guessing at compatibility. The cost is that
# a version bump must move these numbers too -- the bump already edits every package's
# `version`, and `tests/test_packaging.py` fails the build if a pin is left behind.
"keel-core==0.11.2",
"keel-broker-api==0.11.2",
# keel/cli.py and keel/data/cb_client.py still import the Coinbase SDK directly; depending
# on the adapter keeps it available transitively. Phase B deletes those imports and this.
"keel-broker-coinbase==0.11.2",
]
[project.scripts]
keel = "keel.cli:cli"
[build-system]
requires = ["uv_build>=0.10.4,<0.13.0"]
build-backend = "uv_build"
[tool.uv.build-backend]
module-root = ""
# The DISTRIBUTION is `keel-trader` (the name `keel` is taken on PyPI by an unrelated project),
# but the import package and the CLI command stay `keel`. Without this the backend would infer
# `keel_trader/` from the distribution name.
module-name = "keel"
# Ship the default config template inside the wheel so `keel init-config` can write it out on a
# fresh install (the wheel otherwise contains only .py files).
artifacts = ["keel/templates/*.yaml"]
[tool.uv.workspace]
members = ["packages/*"]
[tool.uv.sources]
keel-core = { workspace = true }
keel-broker-api = { workspace = true }
keel-broker-coinbase = { workspace = true }
keel-broker-alpaca = { workspace = true }
keel-broker-fake = { workspace = true }
keel-broker-kraken = { workspace = true }
keel-broker-robinhood = { workspace = true }
[dependency-groups]
dev = [
"mypy>=1.18.0",
"pytest>=9.1.1",
# Dev-only, like every entry below: optuna powers the RESEARCH-side parameter study
# (keel/research/tuning.py, issue #476) and is imported lazily inside run_study only,
# so the shipped wheel and every runtime path stay clean of it. It rides the dev group
# (uv sync's default) rather than its own group so the study's determinism tests
# actually run in CI; uninstalling it must never break `import keel.research.tuning`.
"optuna>=4.5.0",
# tests/test_security_scans.py parses .github/dependabot.yml directly, so the test
# suite imports pyyaml itself rather than riding keel-core's transitive copy (the
# rule the [project] comment above states for `keel/`, applied where it now applies).
"pyyaml>=6.0.2",
# Only `code-quality.yml` needs this: SonarQube reports coverage as a first-class metric and
# has nothing to show without a coverage XML to import. It is deliberately NOT wired into the
# default `pytest` invocation -- `ci.yml` and `release.yml` still run a plain `pytest -q`,
# because measuring coverage costs wall-clock time on every run to produce a number those two
# workflows do not read. The coverage run is opt-in via `--cov`, and only the Sonar job opts in.
"pytest-cov>=7.0.0",
"ruff>=0.15.21",
# Dev-only on purpose: the fake venue exists to exert design pressure on the port and to
# prove two-plugin discovery. A production engine must never have it installed.
"keel-broker-fake",
# Dev-only for a different reason: Robinhood is an OPTIONAL venue, not one keel needs in
# order to run. Making it a runtime dependency of `keel-trader` would put an Ed25519 stack
# (pynacl) into every install for an adapter the live path cannot even reach today --
# nothing constructs it, `keel/commands/_common.py` still builds `CoinbaseClient` directly,
# and the broker-port migration has not landed. Coinbase is a hard dependency only because
# `keel/` still imports its SDK directly; no such import exists for this one, so the
# workspace entry above plus this line is the whole wiring. It is here rather than nowhere
# so the conformance suite actually runs against it in CI. Users who want the venue install
# `keel-broker-robinhood` themselves and entry-point discovery picks it up.
"keel-broker-robinhood",
# Dev-only for the same reason as Robinhood: Alpaca is an optional venue (the Phase 12
# equities milestone). It rides the dev group so the conformance suite runs against it
# in CI; a deployment that wants equities installs `keel-broker-alpaca` itself and
# entry-point discovery picks it up. Nothing in `keel/` imports it.
"keel-broker-alpaca",
# Dev-only like the venues above, and doubly so: Kraken is an optional venue whose
# adapter is a STUB (#313) -- port-complete, but every data/market method raises
# NotImplementedError, so it can never be selected by a deployment that expects data.
# It rides the dev group so the registry (`keel brokers list`) and the stub's own tests
# run in CI; there is no conformance suite for it yet because there is nothing to conform.
"keel-broker-kraken",
]
# Ruff config lives in ruff.toml at the repo root. A ruff.toml takes precedence over
# [tool.ruff] here, so keeping a copy in both places would leave silently-dead settings.
[tool.mypy]
python_version = "3.11"
files = ["packages", "keel", "tests"]
# Implied by `--strict`, but mypy rejects it in a per-module section ("Per-module sections
# should only specify per-module flags"), so it is stated here rather than in the broker block
# below. It is already mypy's own default, so this line changes no behaviour today -- it is
# here so the setting stays explicit if that default ever flips.
warn_redundant_casts = true
# New packages are strict from birth.
#
# ⚠️ These are the flags `--strict` bundles, listed one by one INSTEAD of `strict = true`,
# because `strict` is not actually a per-module setting: mypy applies it GLOBALLY no matter
# which `module` pattern the section carries (a section naming a module that does not exist
# turns it on for the whole run just the same). Written as `strict = true` here, this section
# silently type-checked `keel.*`, `keel_core.*` and `tests.*` under full strict mode too --
# invisible only because all three carry `ignore_errors` below and so never printed what it
# found. The bug surfaces the moment a module is ungated: dropping `keel.*` from the exempt
# list turned up 131 errors where default mode finds 45. Keep this list expanded; re-collapsing
# it to `strict = true` re-breaks the scoping. If a future mypy adds a strict-implied flag,
# add it here as well -- `tests/test_packaging.py::test_broker_strict_flags_match_mypy_strict`
# fails the build when this list and mypy's own `--strict` bundle drift apart.
[[tool.mypy.overrides]]
module = [
"keel_broker_api.*",
"keel_broker_alpaca.*",
"keel_broker_coinbase.*",
"keel_broker_fake.*",
"keel_broker_kraken.*",
"keel_broker_robinhood.*",
]
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
# `warn_redundant_casts` belongs to the bundle too but is global-only; see `[tool.mypy]` above.
warn_unused_ignores = true
warn_return_any = true
no_implicit_reexport = true
strict_equality = true
extra_checks = true
# The suite is exempt until its modules move out (monorepo spec steps 4-7). `keel.*` came off
# this list once its default-mode errors were fixed: it is CHECKED but not yet `strict`, which
# is the next tightening step for it (and the reason it is not simply added to the strict block
# above). Tighten one package at a time, never all at once.
[[tool.mypy.overrides]]
module = ["tests.*"]
ignore_errors = true
# The Coinbase SDK ships no `py.typed`, so every module importing it is an `import-untyped`
# error the moment its importer is checked. `keel/commands/_common.py` and `keel/data/cb_client.py`
# import it directly (the broker-port migration has not removed those yet -- see the note on the
# `keel-broker-coinbase` dependency above). Scoped to the SDK, NOT to our modules: our own code
# stays checked, only the untyped third-party import is waved through, exactly as the broker
# adapter already has to do.
[[tool.mypy.overrides]]
module = "coinbase.*"
ignore_missing_imports = true
# keel-core moved in the previous plan but predates strict mode; it is tightened
# when its remaining consumers migrate.
[[tool.mypy.overrides]]
module = ["keel_core.*"]
ignore_errors = true
# numpy rides in with optuna (the #476 research extra, dev group only) and is reached only
# by the ONE lazy `import optuna` inside keel/research/tuning.py's runner -- nothing under
# keel/ imports numpy itself. numpy's bundled stubs use PEP 695 `type` statements, which
# this run's python_version=3.11 floor cannot parse, so the transitive crawl is silenced
# here rather than by raising the floor every package in this workspace pins.
[[tool.mypy.overrides]]
module = ["numpy.*"]
follow_imports = "skip"
# `follow_imports` alone ignores .pyi files by design; numpy ships BUNDLED STUBS whose
# PEP 695 `type` statements cannot parse under the python_version=3.11 floor above, so the
# skip must reach the stubs too.
follow_imports_for_stubs = true
# Coverage is measured only when `--cov` is passed (see the pytest-cov note in [dependency-groups]).
# This section exists so that a bare `--cov` -- with no value -- measures the right thing instead of
# whatever happened to get imported: the shipped code under `keel/` and the workspace packages,
# and nothing else. `tests/` is excluded because a test file's own coverage is a tautology, and
# `scripts/` because those are one-shot operator tools the suite does not drive.
[tool.coverage.run]
source = ["keel", "packages"]
branch = true
# Emit repo-root-relative paths in coverage.xml. Without this, coverage.py writes filenames that
# are relative to each `source` root (`agent.py`, not `keel/agent.py`) and resolves them via
# absolute `<sources>` entries -- which Sonar can only match if the scanner happens to run from the
# identical absolute path. Relative paths make the report portable between the runner and any
# local run, which is the difference between Sonar showing 95% coverage and showing 0%.
relative_files = true
omit = [
# Generated by release.yml at build time and never present in a checkout.
"keel/_build_info.py",
]
[tool.coverage.report]
exclude_also = [
"if TYPE_CHECKING:",
"raise NotImplementedError",
"@overload",
]