-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathpyproject.toml
More file actions
232 lines (221 loc) · 11.6 KB
/
Copy pathpyproject.toml
File metadata and controls
232 lines (221 loc) · 11.6 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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
[build-system]
requires = ["setuptools>=77", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "pybnf"
dynamic = ["version"]
description = "An application for parallel fitting of BioNetGen and SBML models using metaheuristics"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
license = "BSD-3-Clause"
license-files = ["LICENSE"]
authors = [
{ name = "Eshan Mitra" },
{ name = "Ryan Suderman" },
{ name = "Alex Ionkov" },
{ name = "Jacob Neumann" },
{ name = "Bill Hlavacek" },
]
keywords = ["BioNetGen", "BNGL", "SBML", "parameter-estimation", "systems-biology"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"Operating System :: MacOS",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Scientific/Engineering :: Bio-Informatics",
]
dependencies = [
"bngsim>=0.12.2,<1",
"dask>=2024.1.0",
"distributed>=2024.1.0",
"libroadrunner>=1.6.0",
"msgpack>=0.6.2",
"numpy>=1.24",
"paramiko>=2.7",
"pydantic>=2,<3",
"pyparsing>=2.4,<4",
"scipy>=1.10",
"tornado>=6.1",
]
[project.optional-dependencies]
antimony = [
"bngsim[antimony]>=0.12.2,<1",
]
# The PEtab math translator (pybnf.petab.formula, ADR-0035): an expression
# observableFormula is parsed/serialized through petab's sympy-backed math grammar
# (petab.v2.math). OPTIONAL runtime extra -- only the expression import/export path
# imports petab; the bare-name observableFormula path and core stay dependency-free
# (ADR-0019). Stock PyPI petab carries the math grammar, so this is a normal extra a
# user installs with `pip install pybnf[petab]` (the test extra below overrides the
# pin with the dogfooded fork for the BnglModel validation oracle).
petab = [
"petab>=0.8,<1",
]
# The gradient-based reference sampler (job_type = hmc, ADR-0059): blackjax NUTS on
# the analytical model's JAX log-density, for evaluating PyBNF's gradient-free
# samplers (am/dream/p_dream) against reference-grade NUTS. OPTIONAL runtime extra --
# only the HMC path (pybnf.algorithms.samplers.hmc, plus the priors' logpdf_jax and
# the analytical model's nll_jax) imports jax/blackjax, lazily, with a clear install
# hint; core stays numpy/scipy (ADR-0019). A missing extra raises a pointed
# PybnfError naming `pip install pybnf[jax]`, never a bare ImportError (the house
# pattern, mirroring pybnf[petab]). HMC also needs the analytical-expression backend,
# but the canned gaussian/rotated_gaussian targets used as the closed-form oracle are
# hand-written in jax.numpy and need only this extra.
jax = [
"jax>=0.4",
"jaxlib>=0.4",
"blackjax>=1.2",
]
# The ArviZ InferenceData bridge (pybnf.inference_data, ADR-0055): from_pybnf()
# maps a finished MCMC run's Results/samples.txt onto an arviz.InferenceData so
# PyBNF's posterior output is first-class in the ArviZ/bayesplot/loo ecosystem.
# OPTIONAL runtime extra -- only the bridge imports arviz, lazily, with a clear
# install hint; core stays dependency-free (ADR-0019). h5netcdf gives the netCDF
# engine the config-gated auto-emit of Results/inference_data.nc writes through.
# Uncapped across the arviz major boundary: arviz 1.x is a 2026 rewrite onto
# xarray's DataTree (InferenceData -> DataTree, a changed from_dict signature). The
# bridge supports BOTH lines -- the only API difference is the one from_dict
# construction call (pybnf.inference_data._build_idata branches on its signature);
# every downstream access (.posterior/.sample_stats/.attrs/to_netcdf) is identical.
# So we neither pin to the superseded 0.x nor force 1.x, and pip install
# pybnf[arviz] never downgrades or conflicts with a user's existing arviz.
arviz = [
"arviz>=0.17",
"h5netcdf>=1",
# h5netcdf declares h5py only as an optional extra, but its NETCDF4 write path
# (to_netcdf -> Results/inference_data.nc) needs it, so require it explicitly.
"h5py",
]
# Profile-likelihood plots (job_type = profile_likelihood, #467): the driver renders
# Results/profile_likelihood.png (one Delta chi2 panel per parameter) at the end of a run.
# OPTIONAL runtime extra -- matplotlib is imported lazily only in the plotting path, which
# fails soft when it is absent (the profile_*.txt curves + the summary table are written
# regardless); core stays plot-free and dependency-light (ADR-0019).
plot = [
"matplotlib>=3.5",
]
tests = [
"pytest>=7,<10",
"hypothesis>=6,<7",
# Parallel test execution. CI runs `pytest -m "not slow" -n auto`; the local
# pre-push hook mirrors CI, so xdist is a declared test dependency (the CI
# composite action installs it directly too).
"pytest-xdist",
# PEtab v2 export oracle (ADR-0025/0026) + the math translator (ADR-0035): the
# exporter tests validate emitted problems against petab's own checks, and the
# formula tests use petab.v2.math. Test-only -- core stays dependency-free.
# Stock PyPI petab, so this extra (and therefore the published wheel's
# Requires-Dist) carries NO direct URL reference -- PyPI rejects any distribution
# whose metadata names a `git+` ref. The #420 Step B fork that teaches
# libpetab-python to load `language: bngl` problems natively (validating the
# exporter oracle at MODEL level rather than via the register_bngl() monkeypatch)
# is NOT pinned here: it is injected only on the dedicated CI leg through the
# setup-pybnf action's `petab-spec` input (see .github/workflows/tests.yml). Once
# upstream ships native BNGL (PEtab-dev/PEtab#436) even that override goes away.
# register_bngl() stays a working fallback for stock petab, and the oracle/formula
# tests `pytest.importorskip('petab')`, so this is not a hard test requirement.
"petab>=0.8,<1",
# ArviZ InferenceData bridge oracle (ADR-0055): tests/test_inference_data.py
# builds real containers and round-trips them through netCDF, so the bridge is
# exercised in CI rather than skipped. importorskip('arviz') keeps it non-fatal
# for a bare checkout. Uncapped like the runtime extra (the bridge supports both
# the 0.x InferenceData and 1.x DataTree lines); CI exercises whichever resolves.
"arviz>=0.17",
"h5netcdf>=1",
# h5netcdf's NETCDF4 write path needs h5py (declared only as an optional extra
# of h5netcdf); without it the netCDF round-trip tests fail rather than skip.
"h5py",
# HMC reference sampler oracle (ADR-0059): tests/test_hmc.py runs blackjax NUTS on
# the analytical gaussian/rotated_gaussian targets and checks closed-form posterior
# moment recovery, so the gradient path is exercised in CI rather than skipped. The
# module guards on jax/blackjax importability (skipif), so a bare checkout still
# passes. Uncapped like the runtime extra.
"jax>=0.4",
"jaxlib>=0.4",
"blackjax>=1.2",
# Profile-likelihood plot oracle (#467): tests/test_profile_likelihood.py renders the
# profile panels and asserts the PNG lands in Results/, so the plotting path is exercised
# in CI rather than skipped. The plot tests importorskip('matplotlib'), so a bare checkout
# still passes; this mirrors the optional `plot` runtime extra above.
"matplotlib>=3.5",
]
[project.scripts]
pybnf = "pybnf.pybnf:main"
[project.urls]
Homepage = "https://github.com/lanl/PyBNF"
Documentation = "https://lanl.github.io/PyBNF/"
Source = "https://github.com/lanl/PyBNF"
Issues = "https://github.com/lanl/PyBNF/issues"
# Auto-discover every subpackage under pybnf/ rather than hand-maintaining the
# list. A hand-maintained list silently dropped pybnf.priors and pybnf.noise
# from the built wheel when those subpackages were added (the source tree still
# imported them, so it only broke an installed wheel, never a source checkout).
# tests/test_packaging_metadata.py guards that every on-disk subpackage is
# matched by this include pattern.
[tool.setuptools.packages.find]
include = ["pybnf*"]
[tool.setuptools.dynamic]
version = { attr = "pybnf.__version__" }
[tool.ruff]
target-version = "py311"
# Pins ruff's default rule set (pycodestyle E4/E7/E9 + pyflakes F) so local runs
# and CI agree. Line length (E501) and the broader style/lint families are
# intentionally left off for v1; revisit once the codebase is reformatted.
[tool.ruff.lint]
# UP032 (use an f-string over str.format) is enforced as a cheap regression
# guard: the package source is f-string-clean after the UP031/UP032 sweep and
# there are zero UP032 violations repo-wide. UP031 (printf % -> f-string) is
# deliberately NOT gated -- ~290 %-format sites remain on purpose (e.g. '%d'
# over divmod floats, which truncate where an f-string would not, plus the test
# suite's established %-style), so enforcing it would force incorrect rewrites.
extend-select = ["UP032"]
# Pre-existing legacy style that PyBNF does not enforce. Each is either purely
# cosmetic or a behavioral change to "fix", so it is out of scope for the lint
# gate (which must stay mechanical). Items tied to dev/PUNCHLIST.md are tracked
# and fixed there, not here.
ignore = [
"E402", # module-import-not-at-top: intentional (lazy backend guards, test bootstrap)
"E712", # ==True/False: legacy; rewriting can change truthiness semantics (e.g. numpy bools)
"E721", # type(x) == T comparisons: legacy, semantically fine in context
"E722", # bare except: tracked as ROB-4 in dev/PUNCHLIST.md (behavioral fix)
"E741", # ambiguous variable names (l/I/O): legacy
"F841", # unused locals: several are CQ-5 dead code (tracked); common bind-then-assert in tests
]
[tool.ruff.lint.per-file-ignores]
"tests/**" = [
"E702", # multiple-statements-on-one-line (semicolons): established test-file style
"F402", # import shadowed by loop variable
]
# context.py is a re-export shim: test modules do `from .context import data`,
# so its imports are "unused" only within the file itself.
"tests/context.py" = ["F401"]
# Teaching notebooks: compact grouped imports (`import os, tempfile`) and one-line
# plot/setup statements (`plt.tight_layout(); plt.show()`) are idiomatic in a cell
# and read better there than split across lines -- the same E702 stance as tests/**.
# Substantive checks (unused imports F401, empty f-strings F541, undefined names)
# stay enforced on the cells.
"examples/notebooks/*.ipynb" = ["E401", "E702"]
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
addopts = "-m 'not slow and not recovery'"
markers = [
"slow: long-running statistical recovery tests; deselected by default, run with `-m slow`",
"recovery: synthetic-data parameter-recovery fits through the real bngsim backend; opt-in, run with `-m recovery` (needs bngsim + BNG2.pl)",
"newera: fast new-era (edition-2) validation surface (#436) -- backend-free import/export round-trips (run in default CI) plus a tiny new-era recovery sub-tier (runs by default where bngsim is present, skips otherwise); select with `-m newera`",
"integration: end-to-end algorithm runs against analytical targets (no simulation backend)",
"bngsim: requires bngsim installed and PYBNF_NO_BNGSIM unset",
"bngsim_nfsim: requires bngsim built with NFsim",
"bngsim_rulemonkey: requires bngsim built with RuleMonkey",
"bngsim_sbml: requires bngsim built with libsbml",
"bngsim_antimony: requires bngsim + antimony Python package",
"roadrunner: requires libroadrunner",
"bionetgen: requires a working BNG2.pl on PATH",
"arviz: requires the optional arviz extra (the InferenceData bridge); skips otherwise",
]