xenosite-forest 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ # Caches and virtualenvs
2
+ .venv/
3
+ .pytest_cache/
4
+ .hypothesis/
5
+ .ruff_cache/
6
+ .mypy_cache/
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ *.egg-info/
11
+ .python-version
12
+
13
+ # Build artifacts
14
+ build/
15
+ dist/
16
+ src/xenosite/forest/_version.py
17
+
18
+ # Editors and OS
19
+ .vscode/
20
+ .idea/
21
+ .DS_Store
22
+ *.swp
23
+ *.bak
24
+
25
+ # Secrets and local env
26
+ .env
27
+ .env.*
28
+
29
+ # Local data (never ship)
30
+ data/
31
+ _api
32
+ .cenv
33
+ .devcontainer
@@ -0,0 +1,39 @@
1
+ cff-version: 1.2.0
2
+ message: If you use this software, please cite the Metabolic Forest paper.
3
+ title: xenosite.forest
4
+ authors:
5
+ - family-names: Hughes
6
+ given-names: Tyler B.
7
+ - family-names: Dang
8
+ given-names: Na Le
9
+ - family-names: Kumar
10
+ given-names: Ayush
11
+ - family-names: Flynn
12
+ given-names: Noah R.
13
+ - family-names: Swamidass
14
+ given-names: S. Joshua
15
+ email: swamidass@gmail.com
16
+ license: MIT
17
+ repository-code: https://github.com/swamidasslab/xenosite-forest
18
+ url: https://xenosite.org
19
+ preferred-citation:
20
+ type: article
21
+ title: "Metabolic Forest: Predicting the Diverse Structures of Drug Metabolites"
22
+ authors:
23
+ - family-names: Hughes
24
+ given-names: Tyler B.
25
+ - family-names: Dang
26
+ given-names: Na Le
27
+ - family-names: Kumar
28
+ given-names: Ayush
29
+ - family-names: Flynn
30
+ given-names: Noah R.
31
+ - family-names: Swamidass
32
+ given-names: S. Joshua
33
+ journal: Journal of Chemical Information and Modeling
34
+ year: 2020
35
+ volume: "60"
36
+ issue: "10"
37
+ pages: 4702-4716
38
+ doi: 10.1021/acs.jcim.0c00360
39
+ url: https://doi.org/10.1021/acs.jcim.0c00360
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 S. Joshua Swamidass
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.5
2
+ Name: xenosite-forest
3
+ Version: 0.1.0
4
+ Summary: Metabolic Forest: enumerate metabolite structures from reaction rules
5
+ Project-URL: Homepage, https://xenosite.org
6
+ Project-URL: Documentation, https://github.com/swamidasslab/xenosite-forest/blob/main/docs/usage.md
7
+ Project-URL: Repository, https://github.com/swamidasslab/xenosite-forest
8
+ Project-URL: Issues, https://github.com/swamidasslab/xenosite-forest/issues
9
+ Project-URL: Paper, https://doi.org/10.1021/acs.jcim.0c00360
10
+ Author-email: "S. Joshua Swamidass" <swamidass@gmail.com>
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 S. Joshua Swamidass
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: metabolic-forest,metabolism,metabolite,rdkit,xenosite
34
+ Classifier: Intended Audience :: Science/Research
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
42
+ Requires-Python: >=3.10
43
+ Requires-Dist: rdkit>=2023.9.1
44
+ Provides-Extra: network
45
+ Requires-Dist: networkx>=3.2.1; extra == 'network'
46
+ Requires-Dist: tqdm>=4.66.0; extra == 'network'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # xenosite.forest
50
+
51
+ Python implementation of **Metabolic Forest**: enumerate explicit metabolite structures from reaction rules, and search pathways that connect a reactant to a putative product.
52
+
53
+ Site-of-metabolism *prediction* models (epoxidation, quinonation, Phase I, reactivity, and others) are on the web at **[xenosite.org](https://xenosite.org)**. This package is the structure-enumeration engine, not those neural-network models.
54
+
55
+ If you use this software, please cite the Metabolic Forest paper (DOI and BibTeX below).
56
+
57
+ ## Install
58
+
59
+ ```bash
60
+ uv add xenosite-forest
61
+ ```
62
+
63
+ or
64
+
65
+ ```bash
66
+ pip install xenosite-forest
67
+ ```
68
+
69
+ Optional NetworkX helpers for building a metabolite graph:
70
+
71
+ ```bash
72
+ uv add "xenosite-forest[network]"
73
+ ```
74
+
75
+ Requires **Python 3.10+** and RDKit.
76
+
77
+ ## Quick start
78
+
79
+ ```python
80
+ from rdkit import Chem
81
+ from xenosite.forest import bfs, rules, PhaseOneRS
82
+
83
+ # Pathway from ethanol to acetaldehyde
84
+ smiles, steps, mols = next(bfs(["CCO", "CC=O"], ruleset="PhaseOneRS"))
85
+ print(smiles)
86
+ print(steps)
87
+
88
+ # Enumerate hydroxylation products of propane
89
+ for site, products in rules.Hydroxylation().metabolites(Chem.MolFromSmiles("CCC")):
90
+ print(site, [Chem.MolToSmiles(p) for p in products])
91
+
92
+ # Named Phase I ruleset
93
+ print(sorted({rule.name for rule in PhaseOneRS}))
94
+ ```
95
+
96
+ A longer walkthrough is in [`examples/tutorial.ipynb`](https://github.com/swamidasslab/xenosite-forest/blob/main/examples/tutorial.ipynb). API notes are in [`docs/usage.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/usage.md). Rulesets and their papers are in [`docs/rulesets.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md).
97
+
98
+ ### Command line
99
+
100
+ ```bash
101
+ xenosite-forest CCO CC=O --ruleset PhaseOneRS --depth 1
102
+ ```
103
+
104
+ Useful flags: `--all-paths`, `--depth N`, `--phase1` (Phase I site strings), `--max N`, `--ruleset NAME`.
105
+
106
+ ## Rulesets and papers
107
+
108
+ Pass these names to `bfs(..., ruleset=...)` or `load_ruleset(...)`. Full rule lists, Rainbow colors/hex codes, aliases, and BibTeX are in **[`docs/rulesets.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md)**.
109
+
110
+ | Ruleset | What it enumerates | Matched paper |
111
+ | --- | --- | --- |
112
+ | `PhaseOneRS` | Phase I: SO, UO, DH, HD, RD | Dang et al., Metabolic Rainbow, *JCIM* 2020. DOI [10.1021/acs.jcim.9b00836](https://doi.org/10.1021/acs.jcim.9b00836) |
113
+ | `SO` / `UO` / `DH` / `HD` / `RD` | One Rainbow color each (see hex table in docs) | Same Rainbow paper; Forest rule lists differ slightly for HD/RD/DH |
114
+ | `QuinoneFormationRS` (`QF`) | Quinone, quinone-imine, and quinone-methide structures | Hughes & Swamidass, *Chem. Res. Toxicol.* 2017. DOI [10.1021/acs.chemrestox.6b00385](https://doi.org/10.1021/acs.chemrestox.6b00385) |
115
+ | `Bioactivation` (`BA`) | Quinone, epoxidation, nitroaromatic reduction, thiophene S-oxidation | Hughes et al., *Chem. Res. Toxicol.* 2021. DOI [10.1021/acs.chemrestox.0c00417](https://doi.org/10.1021/acs.chemrestox.0c00417) |
116
+ | `Full` | Complete Metabolic Forest generator (Phase I, conjugations, quinone, tautomerization) | Hughes et al., Metabolic Forest, *JCIM* 2020. DOI [10.1021/acs.jcim.0c00360](https://doi.org/10.1021/acs.jcim.0c00360) |
117
+
118
+ Rainbow colorblind-safe hex (Wong / Okabe–Ito, closest to the paper figures): **SO** Stable Oxygenation red `#D55E00`, **UO** Unstable Oxygenation orange `#E69F00`, **DH** Dehydrogenation green `#009E73`, **HD** Hydrolysis blue `#56B4E9`, **RD** Reduction purple `#CC79A7`.
119
+
120
+ Related single-rule papers: epoxidation ([10.1021/acscentsci.5b00131](https://doi.org/10.1021/acscentsci.5b00131)), N-dealkylation ([10.1021/acs.chemrestox.7b00191](https://doi.org/10.1021/acs.chemrestox.7b00191)), UGT glucuronidation ([10.1093/bioinformatics/btw350](https://doi.org/10.1093/bioinformatics/btw350)), glutathione reactivity ([10.1021/acs.chemrestox.5b00017](https://doi.org/10.1021/acs.chemrestox.5b00017)).
121
+
122
+ ## Documentation
123
+
124
+ - **[Rulesets and papers](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md)** — every built-in ruleset, Rainbow colors, and publication BibTeX
125
+ - **[Usage](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/usage.md)** — public API and pathway search
126
+ - **[Tutorial notebook](https://github.com/swamidasslab/xenosite-forest/blob/main/examples/tutorial.ipynb)** — interactive walkthrough
127
+ - **[xenosite.org](https://xenosite.org)** — XenoSite models for sites of metabolism and reactivity
128
+ - **[Source repository](https://github.com/swamidasslab/xenosite-forest)** — code, issues, and releases
129
+
130
+ Import the package as `xenosite.forest`. `xenosite` is a PEP 420 namespace, so other `xenosite.*` packages can be installed alongside this one.
131
+
132
+ ## Citation
133
+
134
+ Please cite Metabolic Forest if you use this package:
135
+
136
+ Hughes, T. B.; Dang, N. L.; Kumar, A.; Flynn, N. R.; Swamidass, S. J.
137
+ Metabolic Forest: Predicting the Diverse Structures of Drug Metabolites.
138
+ *J. Chem. Inf. Model.* **2020**, *60* (10), 4702–4716.
139
+ **DOI:** [10.1021/acs.jcim.0c00360](https://doi.org/10.1021/acs.jcim.0c00360)
140
+
141
+ BibTeX (copy and paste):
142
+
143
+ ```bibtex
144
+ @article{Hughes2020MetabolicForest,
145
+ title = {Metabolic Forest: Predicting the Diverse Structures of Drug Metabolites},
146
+ author = {Hughes, Tyler B. and Dang, Na Le and Kumar, Ayush and Flynn, Noah R. and Swamidass, S. Joshua},
147
+ journal = {Journal of Chemical Information and Modeling},
148
+ volume = {60},
149
+ number = {10},
150
+ pages = {4702--4716},
151
+ year = {2020},
152
+ doi = {10.1021/acs.jcim.0c00360},
153
+ url = {https://doi.org/10.1021/acs.jcim.0c00360},
154
+ publisher = {American Chemical Society}
155
+ }
156
+ ```
157
+
158
+ A machine-readable citation is also in [`CITATION.cff`](https://github.com/swamidasslab/xenosite-forest/blob/main/CITATION.cff).
159
+
160
+ ## Development
161
+
162
+ ```bash
163
+ git clone https://github.com/swamidasslab/xenosite-forest.git
164
+ cd xenosite-forest
165
+ uv sync --extra network --group dev
166
+ uv run pytest -n auto
167
+ ```
168
+
169
+ Versioning comes from git tags via [hatch-vcs](https://github.com/ofek/hatch-vcs) (setuptools-scm). Tag a release as `vX.Y.Z` (for example `v0.1.0`). On that commit the version is `X.Y.Z`. On later untagged commits it becomes the next patch with a dev suffix and short commit, for example `0.1.1.dev3+gabc1234`. Read it at runtime as `xenosite.forest.__version__`.
170
+
171
+ Pushing a `v*` tag runs [`.github/workflows/release.yml`](https://github.com/swamidasslab/xenosite-forest/blob/main/.github/workflows/release.yml): tests must pass and the resolved version must be a clean `X.Y.Z` before a GitHub Release and PyPI upload. A red tag workflow means do not treat that tag as released. To *block* creating tags unless checks pass, add a GitHub Ruleset on `refs/tags/v*` that requires the `release` / `test` status checks.
172
+
173
+ ### One-time PyPI Trusted Publishing setup
174
+
175
+ No API token is stored in the repo. CI authenticates with [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC).
176
+
177
+ 1. Create the GitHub repo `swamidasslab/xenosite-forest` and push `main`.
178
+ 2. GitHub → **Settings → Environments** → create an environment named exactly `pypi` (optional: require reviewers before deploy).
179
+ 3. On [PyPI](https://pypi.org/manage/account/publishing/): add a **pending** trusted publisher (project does not need to exist yet):
180
+
181
+ | Field | Value |
182
+ | --- | --- |
183
+ | PyPI project name | `xenosite-forest` |
184
+ | Owner | `swamidasslab` |
185
+ | Repository name | `xenosite-forest` |
186
+ | Workflow name | `release.yml` |
187
+ | Environment name | `pypi` |
188
+
189
+ 4. Tag a release (`git tag -a v0.1.0 -m "0.1.0" && git push origin v0.1.0`). The `pypi-publish` job uploads only after tests and build succeed.
190
+
191
+ For a dry run, register the same publisher on [TestPyPI](https://test.pypi.org/manage/account/publishing/) first and temporarily point the publish action at TestPyPI.
192
+
193
+ ## License
194
+
195
+ MIT. See [LICENSE](https://github.com/swamidasslab/xenosite-forest/blob/main/LICENSE).
@@ -0,0 +1,147 @@
1
+ # xenosite.forest
2
+
3
+ Python implementation of **Metabolic Forest**: enumerate explicit metabolite structures from reaction rules, and search pathways that connect a reactant to a putative product.
4
+
5
+ Site-of-metabolism *prediction* models (epoxidation, quinonation, Phase I, reactivity, and others) are on the web at **[xenosite.org](https://xenosite.org)**. This package is the structure-enumeration engine, not those neural-network models.
6
+
7
+ If you use this software, please cite the Metabolic Forest paper (DOI and BibTeX below).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ uv add xenosite-forest
13
+ ```
14
+
15
+ or
16
+
17
+ ```bash
18
+ pip install xenosite-forest
19
+ ```
20
+
21
+ Optional NetworkX helpers for building a metabolite graph:
22
+
23
+ ```bash
24
+ uv add "xenosite-forest[network]"
25
+ ```
26
+
27
+ Requires **Python 3.10+** and RDKit.
28
+
29
+ ## Quick start
30
+
31
+ ```python
32
+ from rdkit import Chem
33
+ from xenosite.forest import bfs, rules, PhaseOneRS
34
+
35
+ # Pathway from ethanol to acetaldehyde
36
+ smiles, steps, mols = next(bfs(["CCO", "CC=O"], ruleset="PhaseOneRS"))
37
+ print(smiles)
38
+ print(steps)
39
+
40
+ # Enumerate hydroxylation products of propane
41
+ for site, products in rules.Hydroxylation().metabolites(Chem.MolFromSmiles("CCC")):
42
+ print(site, [Chem.MolToSmiles(p) for p in products])
43
+
44
+ # Named Phase I ruleset
45
+ print(sorted({rule.name for rule in PhaseOneRS}))
46
+ ```
47
+
48
+ A longer walkthrough is in [`examples/tutorial.ipynb`](https://github.com/swamidasslab/xenosite-forest/blob/main/examples/tutorial.ipynb). API notes are in [`docs/usage.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/usage.md). Rulesets and their papers are in [`docs/rulesets.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md).
49
+
50
+ ### Command line
51
+
52
+ ```bash
53
+ xenosite-forest CCO CC=O --ruleset PhaseOneRS --depth 1
54
+ ```
55
+
56
+ Useful flags: `--all-paths`, `--depth N`, `--phase1` (Phase I site strings), `--max N`, `--ruleset NAME`.
57
+
58
+ ## Rulesets and papers
59
+
60
+ Pass these names to `bfs(..., ruleset=...)` or `load_ruleset(...)`. Full rule lists, Rainbow colors/hex codes, aliases, and BibTeX are in **[`docs/rulesets.md`](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md)**.
61
+
62
+ | Ruleset | What it enumerates | Matched paper |
63
+ | --- | --- | --- |
64
+ | `PhaseOneRS` | Phase I: SO, UO, DH, HD, RD | Dang et al., Metabolic Rainbow, *JCIM* 2020. DOI [10.1021/acs.jcim.9b00836](https://doi.org/10.1021/acs.jcim.9b00836) |
65
+ | `SO` / `UO` / `DH` / `HD` / `RD` | One Rainbow color each (see hex table in docs) | Same Rainbow paper; Forest rule lists differ slightly for HD/RD/DH |
66
+ | `QuinoneFormationRS` (`QF`) | Quinone, quinone-imine, and quinone-methide structures | Hughes & Swamidass, *Chem. Res. Toxicol.* 2017. DOI [10.1021/acs.chemrestox.6b00385](https://doi.org/10.1021/acs.chemrestox.6b00385) |
67
+ | `Bioactivation` (`BA`) | Quinone, epoxidation, nitroaromatic reduction, thiophene S-oxidation | Hughes et al., *Chem. Res. Toxicol.* 2021. DOI [10.1021/acs.chemrestox.0c00417](https://doi.org/10.1021/acs.chemrestox.0c00417) |
68
+ | `Full` | Complete Metabolic Forest generator (Phase I, conjugations, quinone, tautomerization) | Hughes et al., Metabolic Forest, *JCIM* 2020. DOI [10.1021/acs.jcim.0c00360](https://doi.org/10.1021/acs.jcim.0c00360) |
69
+
70
+ Rainbow colorblind-safe hex (Wong / Okabe–Ito, closest to the paper figures): **SO** Stable Oxygenation red `#D55E00`, **UO** Unstable Oxygenation orange `#E69F00`, **DH** Dehydrogenation green `#009E73`, **HD** Hydrolysis blue `#56B4E9`, **RD** Reduction purple `#CC79A7`.
71
+
72
+ Related single-rule papers: epoxidation ([10.1021/acscentsci.5b00131](https://doi.org/10.1021/acscentsci.5b00131)), N-dealkylation ([10.1021/acs.chemrestox.7b00191](https://doi.org/10.1021/acs.chemrestox.7b00191)), UGT glucuronidation ([10.1093/bioinformatics/btw350](https://doi.org/10.1093/bioinformatics/btw350)), glutathione reactivity ([10.1021/acs.chemrestox.5b00017](https://doi.org/10.1021/acs.chemrestox.5b00017)).
73
+
74
+ ## Documentation
75
+
76
+ - **[Rulesets and papers](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/rulesets.md)** — every built-in ruleset, Rainbow colors, and publication BibTeX
77
+ - **[Usage](https://github.com/swamidasslab/xenosite-forest/blob/main/docs/usage.md)** — public API and pathway search
78
+ - **[Tutorial notebook](https://github.com/swamidasslab/xenosite-forest/blob/main/examples/tutorial.ipynb)** — interactive walkthrough
79
+ - **[xenosite.org](https://xenosite.org)** — XenoSite models for sites of metabolism and reactivity
80
+ - **[Source repository](https://github.com/swamidasslab/xenosite-forest)** — code, issues, and releases
81
+
82
+ Import the package as `xenosite.forest`. `xenosite` is a PEP 420 namespace, so other `xenosite.*` packages can be installed alongside this one.
83
+
84
+ ## Citation
85
+
86
+ Please cite Metabolic Forest if you use this package:
87
+
88
+ Hughes, T. B.; Dang, N. L.; Kumar, A.; Flynn, N. R.; Swamidass, S. J.
89
+ Metabolic Forest: Predicting the Diverse Structures of Drug Metabolites.
90
+ *J. Chem. Inf. Model.* **2020**, *60* (10), 4702–4716.
91
+ **DOI:** [10.1021/acs.jcim.0c00360](https://doi.org/10.1021/acs.jcim.0c00360)
92
+
93
+ BibTeX (copy and paste):
94
+
95
+ ```bibtex
96
+ @article{Hughes2020MetabolicForest,
97
+ title = {Metabolic Forest: Predicting the Diverse Structures of Drug Metabolites},
98
+ author = {Hughes, Tyler B. and Dang, Na Le and Kumar, Ayush and Flynn, Noah R. and Swamidass, S. Joshua},
99
+ journal = {Journal of Chemical Information and Modeling},
100
+ volume = {60},
101
+ number = {10},
102
+ pages = {4702--4716},
103
+ year = {2020},
104
+ doi = {10.1021/acs.jcim.0c00360},
105
+ url = {https://doi.org/10.1021/acs.jcim.0c00360},
106
+ publisher = {American Chemical Society}
107
+ }
108
+ ```
109
+
110
+ A machine-readable citation is also in [`CITATION.cff`](https://github.com/swamidasslab/xenosite-forest/blob/main/CITATION.cff).
111
+
112
+ ## Development
113
+
114
+ ```bash
115
+ git clone https://github.com/swamidasslab/xenosite-forest.git
116
+ cd xenosite-forest
117
+ uv sync --extra network --group dev
118
+ uv run pytest -n auto
119
+ ```
120
+
121
+ Versioning comes from git tags via [hatch-vcs](https://github.com/ofek/hatch-vcs) (setuptools-scm). Tag a release as `vX.Y.Z` (for example `v0.1.0`). On that commit the version is `X.Y.Z`. On later untagged commits it becomes the next patch with a dev suffix and short commit, for example `0.1.1.dev3+gabc1234`. Read it at runtime as `xenosite.forest.__version__`.
122
+
123
+ Pushing a `v*` tag runs [`.github/workflows/release.yml`](https://github.com/swamidasslab/xenosite-forest/blob/main/.github/workflows/release.yml): tests must pass and the resolved version must be a clean `X.Y.Z` before a GitHub Release and PyPI upload. A red tag workflow means do not treat that tag as released. To *block* creating tags unless checks pass, add a GitHub Ruleset on `refs/tags/v*` that requires the `release` / `test` status checks.
124
+
125
+ ### One-time PyPI Trusted Publishing setup
126
+
127
+ No API token is stored in the repo. CI authenticates with [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC).
128
+
129
+ 1. Create the GitHub repo `swamidasslab/xenosite-forest` and push `main`.
130
+ 2. GitHub → **Settings → Environments** → create an environment named exactly `pypi` (optional: require reviewers before deploy).
131
+ 3. On [PyPI](https://pypi.org/manage/account/publishing/): add a **pending** trusted publisher (project does not need to exist yet):
132
+
133
+ | Field | Value |
134
+ | --- | --- |
135
+ | PyPI project name | `xenosite-forest` |
136
+ | Owner | `swamidasslab` |
137
+ | Repository name | `xenosite-forest` |
138
+ | Workflow name | `release.yml` |
139
+ | Environment name | `pypi` |
140
+
141
+ 4. Tag a release (`git tag -a v0.1.0 -m "0.1.0" && git push origin v0.1.0`). The `pypi-publish` job uploads only after tests and build succeed.
142
+
143
+ For a dry run, register the same publisher on [TestPyPI](https://test.pypi.org/manage/account/publishing/) first and temporarily point the publish action at TestPyPI.
144
+
145
+ ## License
146
+
147
+ MIT. See [LICENSE](https://github.com/swamidasslab/xenosite-forest/blob/main/LICENSE).