fable-pyculator 0.1.0a1__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.
Files changed (28) hide show
  1. fable_pyculator-0.1.0a1/LICENSE +22 -0
  2. fable_pyculator-0.1.0a1/PKG-INFO +267 -0
  3. fable_pyculator-0.1.0a1/README.md +218 -0
  4. fable_pyculator-0.1.0a1/pyproject.toml +87 -0
  5. fable_pyculator-0.1.0a1/setup.cfg +4 -0
  6. fable_pyculator-0.1.0a1/src/fable_pyculator/__init__.py +92 -0
  7. fable_pyculator-0.1.0a1/src/fable_pyculator/controls.py +87 -0
  8. fable_pyculator-0.1.0a1/src/fable_pyculator/discovery.py +618 -0
  9. fable_pyculator-0.1.0a1/src/fable_pyculator/notebook.py +180 -0
  10. fable_pyculator-0.1.0a1/src/fable_pyculator/spec.py +387 -0
  11. fable_pyculator-0.1.0a1/src/fable_pyculator/surface.py +491 -0
  12. fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/PKG-INFO +267 -0
  13. fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/SOURCES.txt +26 -0
  14. fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/dependency_links.txt +1 -0
  15. fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/requires.txt +30 -0
  16. fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/top_level.txt +1 -0
  17. fable_pyculator-0.1.0a1/tests/test_constants.py +19 -0
  18. fable_pyculator-0.1.0a1/tests/test_controls.py +72 -0
  19. fable_pyculator-0.1.0a1/tests/test_discovery.py +199 -0
  20. fable_pyculator-0.1.0a1/tests/test_examples.py +41 -0
  21. fable_pyculator-0.1.0a1/tests/test_fable_workbook_headline_series.py +40 -0
  22. fable_pyculator-0.1.0a1/tests/test_fable_workbook_output_flavour_tags.py +76 -0
  23. fable_pyculator-0.1.0a1/tests/test_fable_workbook_scenario_definition_tables.py +98 -0
  24. fable_pyculator-0.1.0a1/tests/test_fable_workbook_selection_controls.py +93 -0
  25. fable_pyculator-0.1.0a1/tests/test_notebook.py +221 -0
  26. fable_pyculator-0.1.0a1/tests/test_scripts.py +21 -0
  27. fable_pyculator-0.1.0a1/tests/test_spec.py +66 -0
  28. fable_pyculator-0.1.0a1/tests/test_surface.py +375 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UBC FRESH Lab
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.
22
+
@@ -0,0 +1,267 @@
1
+ Metadata-Version: 2.4
2
+ Name: fable-pyculator
3
+ Version: 0.1.0a1
4
+ Summary: FABLE Calculator-specific notebook controls for Modelwright-generated Python models.
5
+ Author: UBC FRESH Lab
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/UBC-FRESH/fable-pyculator
8
+ Project-URL: Documentation, https://ubc-fresh.github.io/fable-pyculator/
9
+ Project-URL: Repository, https://github.com/UBC-FRESH/fable-pyculator
10
+ Project-URL: Issues, https://github.com/UBC-FRESH/fable-pyculator/issues
11
+ Project-URL: Changelog, https://github.com/UBC-FRESH/fable-pyculator/blob/main/CHANGE_LOG.md
12
+ Keywords: fable,spreadsheet-models,jupyter,modelwright,scenario-analysis
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: modelwright[notebook]>=0.1.0a6
25
+ Requires-Dist: openpyxl>=3.1
26
+ Requires-Dist: pandas>=2
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.2; extra == "dev"
29
+ Requires-Dist: pytest>=8; extra == "dev"
30
+ Requires-Dist: ruff>=0.8; extra == "dev"
31
+ Requires-Dist: sphinx>=7; extra == "dev"
32
+ Requires-Dist: sphinx-rtd-theme>=2; extra == "dev"
33
+ Requires-Dist: twine>=5; extra == "dev"
34
+ Provides-Extra: docs
35
+ Requires-Dist: sphinx>=7; extra == "docs"
36
+ Requires-Dist: sphinx-rtd-theme>=2; extra == "docs"
37
+ Provides-Extra: notebook
38
+ Requires-Dist: ipykernel>=6; extra == "notebook"
39
+ Requires-Dist: ipywidgets>=8; extra == "notebook"
40
+ Requires-Dist: matplotlib>=3.8; extra == "notebook"
41
+ Provides-Extra: quality
42
+ Requires-Dist: ruff>=0.8; extra == "quality"
43
+ Provides-Extra: release
44
+ Requires-Dist: build>=1.2; extra == "release"
45
+ Requires-Dist: twine>=5; extra == "release"
46
+ Provides-Extra: test
47
+ Requires-Dist: pytest>=8; extra == "test"
48
+ Dynamic: license-file
49
+
50
+ # FABLE Pyculator
51
+
52
+ FABLE Pyculator is a FABLE Calculator-specific notebook layer built on top of
53
+ Modelwright-generated Python models.
54
+
55
+ The goal is to keep Modelwright generic while collecting FABLE-C conventions in one public package:
56
+
57
+ - discover likely FABLE scenario input controls from workbook structure;
58
+ - declare those controls as named scenario parameters;
59
+ - expose a Jupyter-friendly control surface for scenario changes;
60
+ - run a generated Modelwright model with the selected scenario inputs;
61
+ - render standard FABLE outputs as pandas tables and matplotlib figures.
62
+
63
+ This repository does not store original FABLE Calculator workbooks, generated Python clones, or raw
64
+ validation outputs. Keep those under ignored `tmp/` paths.
65
+
66
+ ## Development Workflow
67
+
68
+ This project uses the same agent-assisted workflow as Modelwright:
69
+
70
+ - read `AGENTS.md`, `ROADMAP.md`, and `CHANGE_LOG.md` before project-shaping work;
71
+ - keep the current plan in `ROADMAP.md`;
72
+ - record completed deliverables in `CHANGE_LOG.md`;
73
+ - use `planning/` for focused investigations and contracts;
74
+ - keep source workbooks, generated models, extracts, logs, and validation reports under ignored
75
+ `tmp/`;
76
+ - once the public GitHub repo and `gh` access exist, map roadmap phases to GitHub parent issues and
77
+ roadmap tasks to child issues;
78
+ - close every phase through a PR back to `main`, with Sphinx docs rebuilt in CI and deployed to
79
+ GitHub Pages after merge.
80
+
81
+ The local remote is expected to be:
82
+
83
+ ```text
84
+ https://github.com/UBC-FRESH/fable-pyculator.git
85
+ ```
86
+
87
+ ## Install For Development
88
+
89
+ Recommended VSCode/Jupyter setup from the `fable-pyculator` repo root:
90
+
91
+ ```bash
92
+ scripts/bootstrap_dev_env.sh
93
+ ```
94
+
95
+ Then select this interpreter as the VSCode notebook kernel:
96
+
97
+ ```text
98
+ .venv/bin/python
99
+ ```
100
+
101
+ Manual equivalent:
102
+
103
+ ```bash
104
+ python -m venv .venv
105
+ .venv/bin/python -m pip install --upgrade pip
106
+ .venv/bin/python -m pip install -e '.[dev,notebook,docs]'
107
+ ```
108
+
109
+ ## Download FABLE Calculators
110
+
111
+ The current Modelwright benchmark metadata points to this public FABLE Calculator Dropbox folder:
112
+
113
+ ```text
114
+ https://www.dropbox.com/scl/fo/ndgldfnq81v794mm8yebe/ADusMz23xtmYKDXoEkiNtJM?rlkey=d87qhjf5zd0pcowd5pfl5qdu7&st=qijm4tta&e=2&dl=0
115
+ ```
116
+
117
+ In this checkout, the three public FABLE-C workbooks are stored under `tmp/private-workbooks/`.
118
+ They are ignored local benchmark artifacts. Verify them with:
119
+
120
+ ```bash
121
+ sha256sum -c benchmarks/fable-calculator/checksums.sha256
122
+ ```
123
+
124
+ The public 2020 FABLE Calculator documentation PDF is tracked under `reference/fable-calculator/`.
125
+
126
+ The core FABLE-C output data surfaces are the consecutive workbook sheets `FOOD`, `PRODUCTION`,
127
+ `TRADE`, `BIODIVERSITY`, `LAND`, `GHG`, and `WATER`.
128
+
129
+ ## Early Notebook Shape
130
+
131
+ ```python
132
+ from fable_pyculator import (
133
+ FableCalculatorSpec,
134
+ OutputIndicator,
135
+ ScenarioControlSurface,
136
+ ScenarioParameter,
137
+ discover_output_tables,
138
+ discover_scenario_definition_tables,
139
+ discover_selection_controls,
140
+ output_table_frame,
141
+ run_scenario,
142
+ scenario_definition_table_frame,
143
+ scenario_definition_tables_for_location,
144
+ )
145
+
146
+ spec = FableCalculatorSpec(
147
+ parameters=[
148
+ ScenarioParameter(name="ambition", label="Scenario ambition", cell_ref="SCENARIOS selection!D20"),
149
+ ],
150
+ outputs=[
151
+ OutputIndicator(name="ghg", label="GHG emissions", cell_ref="SCENARIOS selection!D22", unit="MtCO2e"),
152
+ ],
153
+ )
154
+
155
+ controls = ScenarioControlSurface(spec)
156
+ controls
157
+
158
+ result = run_scenario(generated_model, spec, controls.values())
159
+ result.outputs
160
+ ```
161
+
162
+ For real FABLE-C workbooks, discover the high-level selection controls, scenario-definition tables,
163
+ and output tables:
164
+
165
+ ```python
166
+ selection_controls = discover_selection_controls("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
167
+ definition_tables = discover_scenario_definition_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
168
+ output_tables = discover_output_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
169
+ spec = FableCalculatorSpec(
170
+ selection_controls=selection_controls,
171
+ scenario_definition_tables=definition_tables,
172
+ output_tables=output_tables,
173
+ )
174
+
175
+ scenario_definition_table_frame(spec, "DietTarget")
176
+ scenario_definition_tables_for_location(spec, "S.3")
177
+
178
+ run = run_scenario(generated_model, spec, {"gdp_scen": "SSP1"})
179
+ output_table_frame(run, "ghg_resultsghg")
180
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-8")
181
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="DATA")
182
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-*")
183
+ ```
184
+
185
+ The first 2020 notebook loop helper uses ignored local artifacts by default:
186
+
187
+ ```text
188
+ tmp/private-workbooks/2020_Open_FABLECalculator.xlsx
189
+ tmp/generated-models/fable-2020/generated_fable_2020_model.py
190
+ ```
191
+
192
+ ```python
193
+ from fable_pyculator import run_2020_notebook_loop
194
+
195
+ result = run_2020_notebook_loop({"gdp_scen": "SSP1"})
196
+ result.output_tables.keys()
197
+ result.output_tables["ghg_resultsghg"]
198
+ result.headline_frames["ghg_total_co2e"]
199
+ result.headline_figures["ghg_total_co2e"]
200
+ ```
201
+
202
+ By default the loop renders every discovered output table and every curated headline frame from the
203
+ single generated-model run. Pass `output_table_names` or `headline_series_names` only when you want a
204
+ smaller rendered subset.
205
+
206
+ Tracked notebook example:
207
+
208
+ ```text
209
+ examples/notebooks/fable-pyculator-2020-loop.ipynb
210
+ ```
211
+
212
+ This notebook is intentionally committed after a successful 2020 benchmark run so GitHub can render
213
+ the example tables and figure directly in the browser.
214
+
215
+ In VSCode, point the notebook kernel at the `.venv` created in the `fable-pyculator` repo root.
216
+ The notebook setup cell prints the active environment prefix and warns if the selected kernel does
217
+ not appear to be that repo-local `.venv`.
218
+
219
+ The Sphinx guide expands this into a full workflow under
220
+ `docs/guides/2020-notebook-workflow.rst`, with validation boundaries recorded in
221
+ `docs/guides/validation-scope.rst`.
222
+
223
+ `fable-pyculator` is pre-release. The current alpha line is `0.1.0a1`; alpha releases must not be
224
+ described as stable public API compatibility, full editable scenario-definition widgets, production
225
+ readiness, full generated-model equivalence, or arbitrary country-calculator support.
226
+
227
+ The public API is intentionally small while the FABLE-specific conventions are being discovered from
228
+ real country calculators.
229
+
230
+ ## Build Docs
231
+
232
+ ```bash
233
+ .venv/bin/python -m pip install -e '.[dev,notebook,docs]'
234
+ .venv/bin/sphinx-build -b html docs _build/html -W
235
+ ```
236
+
237
+ The `Docs Pages` GitHub Actions workflow builds Sphinx docs on pull requests to `main` and deploys
238
+ the built HTML to GitHub Pages after merges to `main`.
239
+
240
+ GitHub Pages URL:
241
+
242
+ ```text
243
+ https://ubc-fresh.github.io/fable-pyculator/
244
+ ```
245
+
246
+ See `docs/guides/release-deployment.rst` for the release and deployment runbook.
247
+
248
+ ## Release Checks
249
+
250
+ Build and inspect release artifacts locally:
251
+
252
+ ```bash
253
+ scripts/check_release_artifacts.sh
254
+ ```
255
+
256
+ Release checks write build outputs under ignored `tmp/release-checks/`.
257
+
258
+ ## Default Checks
259
+
260
+ ```bash
261
+ .venv/bin/python -m ruff check .
262
+ .venv/bin/python -m pytest
263
+ .venv/bin/sphinx-build -b html docs _build/html -W
264
+ .venv/bin/python scripts/verify_docs_theme.py _build/html
265
+ scripts/check_release_artifacts.sh
266
+ sha256sum -c benchmarks/fable-calculator/checksums.sha256
267
+ ```
@@ -0,0 +1,218 @@
1
+ # FABLE Pyculator
2
+
3
+ FABLE Pyculator is a FABLE Calculator-specific notebook layer built on top of
4
+ Modelwright-generated Python models.
5
+
6
+ The goal is to keep Modelwright generic while collecting FABLE-C conventions in one public package:
7
+
8
+ - discover likely FABLE scenario input controls from workbook structure;
9
+ - declare those controls as named scenario parameters;
10
+ - expose a Jupyter-friendly control surface for scenario changes;
11
+ - run a generated Modelwright model with the selected scenario inputs;
12
+ - render standard FABLE outputs as pandas tables and matplotlib figures.
13
+
14
+ This repository does not store original FABLE Calculator workbooks, generated Python clones, or raw
15
+ validation outputs. Keep those under ignored `tmp/` paths.
16
+
17
+ ## Development Workflow
18
+
19
+ This project uses the same agent-assisted workflow as Modelwright:
20
+
21
+ - read `AGENTS.md`, `ROADMAP.md`, and `CHANGE_LOG.md` before project-shaping work;
22
+ - keep the current plan in `ROADMAP.md`;
23
+ - record completed deliverables in `CHANGE_LOG.md`;
24
+ - use `planning/` for focused investigations and contracts;
25
+ - keep source workbooks, generated models, extracts, logs, and validation reports under ignored
26
+ `tmp/`;
27
+ - once the public GitHub repo and `gh` access exist, map roadmap phases to GitHub parent issues and
28
+ roadmap tasks to child issues;
29
+ - close every phase through a PR back to `main`, with Sphinx docs rebuilt in CI and deployed to
30
+ GitHub Pages after merge.
31
+
32
+ The local remote is expected to be:
33
+
34
+ ```text
35
+ https://github.com/UBC-FRESH/fable-pyculator.git
36
+ ```
37
+
38
+ ## Install For Development
39
+
40
+ Recommended VSCode/Jupyter setup from the `fable-pyculator` repo root:
41
+
42
+ ```bash
43
+ scripts/bootstrap_dev_env.sh
44
+ ```
45
+
46
+ Then select this interpreter as the VSCode notebook kernel:
47
+
48
+ ```text
49
+ .venv/bin/python
50
+ ```
51
+
52
+ Manual equivalent:
53
+
54
+ ```bash
55
+ python -m venv .venv
56
+ .venv/bin/python -m pip install --upgrade pip
57
+ .venv/bin/python -m pip install -e '.[dev,notebook,docs]'
58
+ ```
59
+
60
+ ## Download FABLE Calculators
61
+
62
+ The current Modelwright benchmark metadata points to this public FABLE Calculator Dropbox folder:
63
+
64
+ ```text
65
+ https://www.dropbox.com/scl/fo/ndgldfnq81v794mm8yebe/ADusMz23xtmYKDXoEkiNtJM?rlkey=d87qhjf5zd0pcowd5pfl5qdu7&st=qijm4tta&e=2&dl=0
66
+ ```
67
+
68
+ In this checkout, the three public FABLE-C workbooks are stored under `tmp/private-workbooks/`.
69
+ They are ignored local benchmark artifacts. Verify them with:
70
+
71
+ ```bash
72
+ sha256sum -c benchmarks/fable-calculator/checksums.sha256
73
+ ```
74
+
75
+ The public 2020 FABLE Calculator documentation PDF is tracked under `reference/fable-calculator/`.
76
+
77
+ The core FABLE-C output data surfaces are the consecutive workbook sheets `FOOD`, `PRODUCTION`,
78
+ `TRADE`, `BIODIVERSITY`, `LAND`, `GHG`, and `WATER`.
79
+
80
+ ## Early Notebook Shape
81
+
82
+ ```python
83
+ from fable_pyculator import (
84
+ FableCalculatorSpec,
85
+ OutputIndicator,
86
+ ScenarioControlSurface,
87
+ ScenarioParameter,
88
+ discover_output_tables,
89
+ discover_scenario_definition_tables,
90
+ discover_selection_controls,
91
+ output_table_frame,
92
+ run_scenario,
93
+ scenario_definition_table_frame,
94
+ scenario_definition_tables_for_location,
95
+ )
96
+
97
+ spec = FableCalculatorSpec(
98
+ parameters=[
99
+ ScenarioParameter(name="ambition", label="Scenario ambition", cell_ref="SCENARIOS selection!D20"),
100
+ ],
101
+ outputs=[
102
+ OutputIndicator(name="ghg", label="GHG emissions", cell_ref="SCENARIOS selection!D22", unit="MtCO2e"),
103
+ ],
104
+ )
105
+
106
+ controls = ScenarioControlSurface(spec)
107
+ controls
108
+
109
+ result = run_scenario(generated_model, spec, controls.values())
110
+ result.outputs
111
+ ```
112
+
113
+ For real FABLE-C workbooks, discover the high-level selection controls, scenario-definition tables,
114
+ and output tables:
115
+
116
+ ```python
117
+ selection_controls = discover_selection_controls("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
118
+ definition_tables = discover_scenario_definition_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
119
+ output_tables = discover_output_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
120
+ spec = FableCalculatorSpec(
121
+ selection_controls=selection_controls,
122
+ scenario_definition_tables=definition_tables,
123
+ output_tables=output_tables,
124
+ )
125
+
126
+ scenario_definition_table_frame(spec, "DietTarget")
127
+ scenario_definition_tables_for_location(spec, "S.3")
128
+
129
+ run = run_scenario(generated_model, spec, {"gdp_scen": "SSP1"})
130
+ output_table_frame(run, "ghg_resultsghg")
131
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-8")
132
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="DATA")
133
+ output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-*")
134
+ ```
135
+
136
+ The first 2020 notebook loop helper uses ignored local artifacts by default:
137
+
138
+ ```text
139
+ tmp/private-workbooks/2020_Open_FABLECalculator.xlsx
140
+ tmp/generated-models/fable-2020/generated_fable_2020_model.py
141
+ ```
142
+
143
+ ```python
144
+ from fable_pyculator import run_2020_notebook_loop
145
+
146
+ result = run_2020_notebook_loop({"gdp_scen": "SSP1"})
147
+ result.output_tables.keys()
148
+ result.output_tables["ghg_resultsghg"]
149
+ result.headline_frames["ghg_total_co2e"]
150
+ result.headline_figures["ghg_total_co2e"]
151
+ ```
152
+
153
+ By default the loop renders every discovered output table and every curated headline frame from the
154
+ single generated-model run. Pass `output_table_names` or `headline_series_names` only when you want a
155
+ smaller rendered subset.
156
+
157
+ Tracked notebook example:
158
+
159
+ ```text
160
+ examples/notebooks/fable-pyculator-2020-loop.ipynb
161
+ ```
162
+
163
+ This notebook is intentionally committed after a successful 2020 benchmark run so GitHub can render
164
+ the example tables and figure directly in the browser.
165
+
166
+ In VSCode, point the notebook kernel at the `.venv` created in the `fable-pyculator` repo root.
167
+ The notebook setup cell prints the active environment prefix and warns if the selected kernel does
168
+ not appear to be that repo-local `.venv`.
169
+
170
+ The Sphinx guide expands this into a full workflow under
171
+ `docs/guides/2020-notebook-workflow.rst`, with validation boundaries recorded in
172
+ `docs/guides/validation-scope.rst`.
173
+
174
+ `fable-pyculator` is pre-release. The current alpha line is `0.1.0a1`; alpha releases must not be
175
+ described as stable public API compatibility, full editable scenario-definition widgets, production
176
+ readiness, full generated-model equivalence, or arbitrary country-calculator support.
177
+
178
+ The public API is intentionally small while the FABLE-specific conventions are being discovered from
179
+ real country calculators.
180
+
181
+ ## Build Docs
182
+
183
+ ```bash
184
+ .venv/bin/python -m pip install -e '.[dev,notebook,docs]'
185
+ .venv/bin/sphinx-build -b html docs _build/html -W
186
+ ```
187
+
188
+ The `Docs Pages` GitHub Actions workflow builds Sphinx docs on pull requests to `main` and deploys
189
+ the built HTML to GitHub Pages after merges to `main`.
190
+
191
+ GitHub Pages URL:
192
+
193
+ ```text
194
+ https://ubc-fresh.github.io/fable-pyculator/
195
+ ```
196
+
197
+ See `docs/guides/release-deployment.rst` for the release and deployment runbook.
198
+
199
+ ## Release Checks
200
+
201
+ Build and inspect release artifacts locally:
202
+
203
+ ```bash
204
+ scripts/check_release_artifacts.sh
205
+ ```
206
+
207
+ Release checks write build outputs under ignored `tmp/release-checks/`.
208
+
209
+ ## Default Checks
210
+
211
+ ```bash
212
+ .venv/bin/python -m ruff check .
213
+ .venv/bin/python -m pytest
214
+ .venv/bin/sphinx-build -b html docs _build/html -W
215
+ .venv/bin/python scripts/verify_docs_theme.py _build/html
216
+ scripts/check_release_artifacts.sh
217
+ sha256sum -c benchmarks/fable-calculator/checksums.sha256
218
+ ```
@@ -0,0 +1,87 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fable-pyculator"
7
+ version = "0.1.0a1"
8
+ description = "FABLE Calculator-specific notebook controls for Modelwright-generated Python models."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "UBC FRESH Lab" }
15
+ ]
16
+ keywords = [
17
+ "fable",
18
+ "spreadsheet-models",
19
+ "jupyter",
20
+ "modelwright",
21
+ "scenario-analysis"
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 3 - Alpha",
25
+ "Intended Audience :: Science/Research",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Python :: 3 :: Only",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Topic :: Scientific/Engineering"
32
+ ]
33
+ dependencies = [
34
+ "modelwright[notebook]>=0.1.0a6",
35
+ "openpyxl>=3.1",
36
+ "pandas>=2"
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "build>=1.2",
42
+ "pytest>=8",
43
+ "ruff>=0.8",
44
+ "sphinx>=7",
45
+ "sphinx-rtd-theme>=2",
46
+ "twine>=5"
47
+ ]
48
+ docs = [
49
+ "sphinx>=7",
50
+ "sphinx-rtd-theme>=2"
51
+ ]
52
+ notebook = [
53
+ "ipykernel>=6",
54
+ "ipywidgets>=8",
55
+ "matplotlib>=3.8"
56
+ ]
57
+ quality = [
58
+ "ruff>=0.8"
59
+ ]
60
+ release = [
61
+ "build>=1.2",
62
+ "twine>=5"
63
+ ]
64
+ test = [
65
+ "pytest>=8"
66
+ ]
67
+
68
+ [project.urls]
69
+ Homepage = "https://github.com/UBC-FRESH/fable-pyculator"
70
+ Documentation = "https://ubc-fresh.github.io/fable-pyculator/"
71
+ Repository = "https://github.com/UBC-FRESH/fable-pyculator"
72
+ Issues = "https://github.com/UBC-FRESH/fable-pyculator/issues"
73
+ Changelog = "https://github.com/UBC-FRESH/fable-pyculator/blob/main/CHANGE_LOG.md"
74
+
75
+ [tool.setuptools.packages.find]
76
+ where = ["src"]
77
+
78
+ [tool.pytest.ini_options]
79
+ testpaths = ["tests"]
80
+ markers = [
81
+ "workbook: tests that require local FABLE workbook artifacts and are skipped unless explicitly enabled"
82
+ ]
83
+
84
+ [tool.ruff]
85
+ line-length = 120
86
+ target-version = "py310"
87
+ extend-exclude = ["tmp"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,92 @@
1
+ """FABLE Calculator-specific notebook helpers for Modelwright-generated models."""
2
+
3
+ from fable_pyculator.discovery import (
4
+ curate_default_headline_series,
5
+ discover_output_tables,
6
+ discover_scenario_parameters,
7
+ discover_scenario_definition_tables,
8
+ discover_selection_controls,
9
+ )
10
+ from fable_pyculator.spec import (
11
+ FABLE_OUTPUT_SURFACE_SHEETS,
12
+ FableCalculatorSpec,
13
+ HeadlinePoint,
14
+ HeadlineSeries,
15
+ OutputIndicator,
16
+ OutputTable,
17
+ ScenarioDefinitionTable,
18
+ ScenarioParameter,
19
+ SelectionControl,
20
+ SelectionOption,
21
+ )
22
+ from fable_pyculator.controls import ScenarioControlSurface
23
+ from fable_pyculator.notebook import (
24
+ DEFAULT_2020_GENERATED_MODEL_PATH,
25
+ DEFAULT_2020_WORKBOOK_PATH,
26
+ DEFAULT_HEADLINE_SERIES,
27
+ DEFAULT_OUTPUT_TABLES,
28
+ NotebookLoopResult,
29
+ build_2020_notebook_spec,
30
+ load_generated_model,
31
+ run_2020_notebook_loop,
32
+ run_notebook_loop,
33
+ )
34
+ from fable_pyculator.surface import (
35
+ ScenarioRun,
36
+ headline_frame,
37
+ headline_frames,
38
+ output_table_frame,
39
+ output_tables,
40
+ outputs_frame,
41
+ plot_headline,
42
+ plot_outputs,
43
+ run_scenario,
44
+ scenario_definition_table_frame,
45
+ scenario_definition_tables,
46
+ scenario_definition_tables_for_location,
47
+ scenario_frame,
48
+ )
49
+
50
+ __version__ = "0.1.0a1"
51
+
52
+ __all__ = [
53
+ "FableCalculatorSpec",
54
+ "FABLE_OUTPUT_SURFACE_SHEETS",
55
+ "DEFAULT_2020_GENERATED_MODEL_PATH",
56
+ "DEFAULT_2020_WORKBOOK_PATH",
57
+ "DEFAULT_HEADLINE_SERIES",
58
+ "DEFAULT_OUTPUT_TABLES",
59
+ "HeadlinePoint",
60
+ "HeadlineSeries",
61
+ "NotebookLoopResult",
62
+ "OutputIndicator",
63
+ "OutputTable",
64
+ "ScenarioControlSurface",
65
+ "ScenarioDefinitionTable",
66
+ "ScenarioParameter",
67
+ "ScenarioRun",
68
+ "SelectionControl",
69
+ "SelectionOption",
70
+ "__version__",
71
+ "build_2020_notebook_spec",
72
+ "curate_default_headline_series",
73
+ "discover_output_tables",
74
+ "discover_scenario_definition_tables",
75
+ "discover_scenario_parameters",
76
+ "discover_selection_controls",
77
+ "headline_frame",
78
+ "headline_frames",
79
+ "output_table_frame",
80
+ "output_tables",
81
+ "outputs_frame",
82
+ "plot_headline",
83
+ "plot_outputs",
84
+ "load_generated_model",
85
+ "run_2020_notebook_loop",
86
+ "run_notebook_loop",
87
+ "run_scenario",
88
+ "scenario_definition_table_frame",
89
+ "scenario_definition_tables",
90
+ "scenario_definition_tables_for_location",
91
+ "scenario_frame",
92
+ ]