-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathpyproject.toml
More file actions
217 lines (194 loc) · 6.98 KB
/
Copy pathpyproject.toml
File metadata and controls
217 lines (194 loc) · 6.98 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
# Main project metadata
[project]
name = 'jquantstats'
version = "0.10.0"
description = "Analytics for quants"
authors = [{name='tschm', email= 'thomas.schmelzer@gmail.com'}]
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"jinja2>=3.1.0",
"narwhals>=2.0.0",
"numpy>=2.0.0",
"plotly>=6.1.1",
"polars>=1.43.0",
"scipy>=1.14.1"
]
license = "MIT"
license-files = ["LICENSE"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Financial and Insurance Industry",
"Intended Audience :: Science/Research",
"Topic :: Office/Business :: Financial",
"Topic :: Scientific/Engineering :: Mathematics",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
# Project URLs for documentation and reference
[project.urls]
Homepage = "https://github.com/jebel-quant/jquantstats"
Repository = "https://github.com/jebel-quant/jquantstats"
# Optional dependencies that can be installed with extras (e.g., pip install jquantstats[plot])
[project.optional-dependencies]
plot = ["kaleido>=1.3.0,<2"]
web = [
"fastapi>=0.115.0",
"uvicorn>=0.32.0",
"python-multipart>=0.0.12",
]
[dependency-groups]
dev = [
"pandas>=2.2.3", # required by quantstats (comparison tests only — not a runtime dependency)
"pyarrow>=22.0.0",
"yfinance==1.5.2",
"ipython==9.15.0",
"quantstats==0.0.81", # reference implementation used in test_quantstats.py for metric validation
"httpx>=0.28.1",
"marimo>=0.23.6",
]
test = [
"pytest>=8.0",
"pytest-cov>=6.0",
"pytest-html>=4.0",
"pytest-mock>=3.0",
"pytest-xdist>=3.0",
"pytest-timeout>=2.0",
"pytest-benchmark>=5.2.3",
"mutmut==2.5.1", # pinned: the 3.x CLI is incompatible with bin/mutation_gate.py
"hypothesis>=6.150.0",
"syrupy>=4.9.1",
"pygal>=3.1.0",
"python-dotenv>=1.0",
]
lint = [
"pre-commit>=4.0",
"ty>=0.0.30",
"import-linter>=2.0", # enforces the layering contracts in [tool.importlinter] via `make arch`
]
# Build system configuration
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# Configuration for wheel build
[tool.hatch.build.targets.wheel]
packages = ["src/jquantstats"]
# Configuration for what files to include in the build
[tool.hatch.build]
include = [
"LICENSE", # Ensure the LICENSE file is included in your package
"README.md",
"src/jquantstats",
"src/jquantstats/py.typed",
]
# Bandit security linter configuration
[tool.bandit]
exclude_dirs = ["src/tests"] # Exclude test directories from security scanning
# Ignore specific dependency issues.
#
# DEP002 flags a declared dependency with no import site. The three below have
# none by design, so the ignore records a fact rather than hiding a gap:
# kaleido - Plotly's static image-export backend. Selected at runtime
# by plotly.io, never imported by us.
# uvicorn - ASGI server for api/app.py. Invoked as a command
# (`uvicorn api.app:app`), not imported.
# python-multipart - parses multipart/form-data for FastAPI's Form/UploadFile.
# Imported by Starlette, never by us.
# fastapi is deliberately absent: api/ is now part of the deptry scan (see the
# DEPTRY_FOLDERS line in the Makefile), so its import there is observed directly.
[tool.deptry.per_rule_ignores]
DEP002 = ["kaleido", "uvicorn", "python-multipart"]
# Package to module name mapping
[tool.deptry.package_module_name_map]
jinja2 = "jinja2"
numpy = "numpy"
plotly = "plotly"
polars = "polars"
pandas = "pandas"
scipy = "scipy"
kaleido = "kaleido"
fastapi = "fastapi"
uvicorn = "uvicorn"
yfinance = "yfinance"
ipython = "ipython"
quantstats = "quantstats"
marimo = "marimo"
hypothesis = "hypothesis"
narwhals = "narwhals"
python-multipart = "python_multipart"
pyarrow = "pyarrow"
httpx = "httpx"
# Coverage configuration
[tool.coverage.run]
branch = true
[tool.coverage.report]
fail_under = 100
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:", # type-only imports are never executed at runtime
"@overload", # overload stubs have no runtime body
]
# Interrogate docstring coverage configuration
[tool.mypy]
[[tool.mypy.overrides]]
module = ["plotly.*", "scipy.*"]
ignore_missing_imports = true
[tool.interrogate]
fail-under = 100
ignore-init-method = true
ignore-magic = true
ignore-overloaded-functions = true
# Test-layout parity (rhiza check_test_layout): tests here are organised by
# behaviour under tests/test_jquantstats/… rather than mirroring src/ 1:1, and
# per-module coverage is guaranteed by the 100% line+branch pytest gate above
# (a stronger guarantee than file-mirroring). Opt out of the 1:1 mirror rule.
[tool.check_test_layout]
enforce = false
# Keep this string free of a literal `%`: tools that read [tool.*] tables through
# configparser (radon, for one) treat it as interpolation syntax and crash outright.
reason = "Tests are organised by behaviour under tests/test_jquantstats/; per-module coverage is guaranteed by the full line-and-branch pytest coverage gate rather than 1:1 file mirroring."
# Declares every location the release version lives, so `bump-my-version` rewrites
# them all in one step. Without this, a bump silently touches no files and the
# release CI fails its pyproject-version-vs-tag check.
[tool.bumpversion]
current_version = "0.10.0"
# Anchored to the [project] table on purpose: search/replace applies to every match
# in the file, so an unanchored `version = "..."` would also rewrite any [tool.*]
# table that happens to share the current version number.
[[tool.bumpversion.files]]
filename = "pyproject.toml"
regex = true
search = '(?ms)^\[project\]((?:(?!^\[)[\s\S])*?)^version = "{current_version}"'
replace = '[project]\1version = "{new_version}"'
# Architectural import contracts (import-linter), run via `make arch` and hooked
# into `make test`. These encode the layering that src/jquantstats/_protocol.py
# describes in prose: the analytics subpackages annotate against the structural
# Protocols and must never reach for the concrete Data / Portfolio classes.
#
# Type-checking-only imports are excluded, because `if TYPE_CHECKING: from ..data
# import Data` is exactly the sanctioned pattern here — it costs nothing at
# runtime and forms no import cycle. Only real runtime imports are contract
# violations.
[tool.importlinter]
root_package = "jquantstats"
exclude_type_checking_imports = true
[[tool.importlinter.contracts]]
name = "analytics subpackages must not import the concrete Data/Portfolio at runtime"
type = "forbidden"
source_modules = [
"jquantstats._stats",
"jquantstats._plots",
"jquantstats._reports",
"jquantstats._utils",
]
forbidden_modules = [
"jquantstats.data",
"jquantstats.portfolio",
]
[[tool.importlinter.contracts]]
name = "the Data reshape mixin must not import Data"
type = "forbidden"
source_modules = ["jquantstats._data_reshape"]
forbidden_modules = ["jquantstats.data"]