-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathMakefile
More file actions
353 lines (311 loc) · 10.6 KB
/
Makefile
File metadata and controls
353 lines (311 loc) · 10.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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
PACKAGE := iadpython
GITHUB_USER := scottprahl
# -------- venv config --------
PY_VERSION ?= 3.14
VENV ?= .venv
PY := /opt/homebrew/opt/python@$(PY_VERSION)/bin/python$(PY_VERSION)
PYTHON := $(VENV)/bin/python
PYPROJECT := pyproject.toml
DOCS_DIR := docs
HTML_DIR := $(DOCS_DIR)/_build/html
ROOT := $(abspath .)
OUT_ROOT := $(ROOT)/_site
OUT_DIR := $(OUT_ROOT)/$(PACKAGE)
STAGE_DIR := $(ROOT)/.lite_src
DOIT_DB := $(ROOT)/.jupyterlite.doit.db
LITE_CONFIG := $(ROOT)/$(PACKAGE)/jupyter_lite_config.json
# --- GitHub Pages deploy config ---
PAGES_BRANCH := gh-pages
WORKTREE := .gh-pages
REMOTE := origin
# --- server config (override on CLI if needed) ---
HOST := 127.0.0.1
PORT := 8000
PYTEST := $(VENV)/bin/pytest
PYLINT := $(VENV)/bin/pylint
SPHINX := $(VENV)/bin/sphinx-build
RUFF := $(VENV)/bin/ruff
BLACK := $(VENV)/bin/black
CHECKMANIFEST := $(VENV)/bin/check-manifest
PYROMA := $(PYTHON) -m pyroma
RSTCHECK := $(PYTHON) -m rstcheck
YAMLLINT := $(PYTHON) -m yamllint
PYTEST_OPTS := -q
SPHINX_OPTS := -T -E -b html -d $(DOCS_DIR)/_build/doctrees -D language=en
.PHONY: help
help:
@echo "Build Targets:"
@echo " dist - Build sdist+wheel locally"
@echo " html - Build Sphinx HTML documentation"
@echo " lite - Build jupyterlite sources"
@echo " lab - Start jupyterlab"
@echo " venv - Create/provision the virtual environment ($(VENV))"
@echo ""
@echo "Test Targets:"
@echo " test - Run pytest"
@echo " note-test - Test all notebooks for errors"
@echo ""
@echo "Packaging Targets:"
@echo " rcheck - Distribution release checks"
@echo " manifest-check - Validate MANIFEST"
@echo " pylint-check - Same as lint above"
@echo " pyroma-check - Validate overall packaging"
@echo " black-check - Check formatting with black"
@echo " rst-check - Validate all RST files"
@echo " ruff-check - Lint all .py and .ipynb files"
@echo " yaml-check - Validate YAML files"
@echo ""
@echo "JupyterLite Targets:"
@echo " lite - Build JupyterLite site into $(OUT_DIR)"
@echo " lite-serve - Serve $(OUT_DIR) at http://$(HOST):$(PORT)"
@echo " lite-deploy - Upload to github"
@echo ""
@echo "Clean Targets:"
@echo " clean - Remove build caches and docs output"
@echo " lite-clean - Remove JupyterLite outputs"
@echo " realclean - clean + remove $(VENV)"
# venv bootstrap
$(VENV)/.ready: Makefile $(PYPROJECT)
@echo "==> Ensuring venv at $(VENV) using $(PY)"
@if [ ! -x "$(PY)" ]; then \
echo "❌ Homebrew Python $(PY_VERSION) not found at $(PY)"; \
echo " Try: brew install python@$(PY_VERSION)"; \
exit 1; \
fi
@if [ -d "$(VENV)" ]; then \
if [ ! -x "$(PYTHON)" ]; then \
echo "==> Existing $(VENV) is missing $(PYTHON); recreating"; \
/bin/rm -rf "$(VENV)"; \
else \
VENV_PY_VERSION=$$("$(PYTHON)" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo missing); \
if [ "$$VENV_PY_VERSION" != "$(PY_VERSION)" ]; then \
echo "==> Existing $(VENV) uses Python $$VENV_PY_VERSION; recreating for Python $(PY_VERSION)"; \
/bin/rm -rf "$(VENV)"; \
fi; \
fi; \
fi
@if [ ! -d "$(VENV)" ]; then \
"$(PY)" -m venv "$(VENV)"; \
fi
@if ! "$(PYTHON)" -m pip --version >/dev/null 2>&1; then \
echo "==> Bootstrapping pip in $(VENV)"; \
"$(PYTHON)" -m ensurepip --upgrade; \
fi
@$(PYTHON) -m pip -q install --upgrade pip wheel
@echo "==> Installing iadpython + dev extras"
@$(PYTHON) -m pip install -e ".[dev,docs,lite]"
@touch "$(VENV)/.ready"
@echo "✅ venv ready"
.PHONY: venv
venv: $(VENV)/.ready
@:
.PHONY: dist
dist: venv
$(PYTHON) -m build
.PHONY: lab
lab: venv
@echo "==> Launching JupyterLab using venv ($(PYTHON))"
"$(PYTHON)" -m jupyter lab --ServerApp.root_dir="$(CURDIR)"
.PHONY: test
test: venv
$(PYTEST) $(PYTEST_OPTS) --ignore=tests/test_double.py --ignore=tests/test_all_notebooks.py tests
.PHONY: note-test
note-test: venv
$(PYTEST) --verbose tests/test_all_notebooks.py
@echo "✅ Notebook check complete"
.PHONY: html
html: venv
@mkdir -p "$(HTML_DIR)"
$(SPHINX) $(SPHINX_OPTS) "$(DOCS_DIR)" "$(HTML_DIR)"
@command -v open >/dev/null 2>&1 && open "$(HTML_DIR)/index.html" || true
.PHONY: lint
lint: pylint-check
.PHONY: pylint-check
pylint-check: venv
-@$(PYLINT) .github/scripts/update_citation.py
-@$(PYLINT) iadpython/ad.py
-@$(PYLINT) iadpython/agrid.py
-@$(PYLINT) iadpython/cache.py
-@$(PYLINT) iadpython/combine.py
-@$(PYLINT) iadpython/constants.py
-@$(PYLINT) iadpython/double.py
-@$(PYLINT) iadpython/fresnel.py
-@$(PYLINT) iadpython/grid.py
-@$(PYLINT) iadpython/iad.py
-@$(PYLINT) iadpython/iadcommand.py
-@$(PYLINT) iadpython/nist.py
-@$(PYLINT) iadpython/port.py
-@$(PYLINT) --ignored-modules=scipy.special iadpython/quadrature.py
-@$(PYLINT) --ignored-modules=scipy.special iadpython/redistribution.py
-@$(PYLINT) iadpython/rxt.py
-@$(PYLINT) iadpython/sphere.py
-@$(PYLINT) iadpython/start.py
-@$(PYLINT) iadpython/txt.py
-@$(PYLINT) tests/test_boundary.py
-@$(PYLINT) tests/test_combo.py
-@$(PYLINT) tests/test_fresnel.py
-@$(PYLINT) tests/test_grid.py
-@$(PYLINT) tests/test_iad.py
-@$(PYLINT) tests/test_layer.py
-@$(PYLINT) tests/test_layers.py
-@$(PYLINT) tests/test_nist.py
-@$(PYLINT) tests/test_one_sphere.py
-@$(PYLINT) tests/test_port.py
-@$(PYLINT) tests/test_quadrature.py
-@$(PYLINT) tests/test_redistribution.py
-@$(PYLINT) tests/test_roundtrip_0_spheres.py
-@$(PYLINT) tests/test_roundtrip_1_sphere.py
-@$(PYLINT) tests/test_roundtrip_2_spheres.py
-@$(PYLINT) tests/test_rxt.py
-@$(PYLINT) tests/test_sphere.py
-@$(PYLINT) tests/test_start.py
-@$(PYLINT) tests/test_txt.py
-@$(PYLINT) tests/test_ur1_uru.py
-@$(PYLINT) tests_iadc/test_iadc.py
-@$(PYLINT) tests_iadc/test_performance.py
-@$(PYLINT) tests/test_all_notebooks.py
.PHONY: yaml-check
yaml-check: venv
-@$(YAMLLINT) .github/workflows/citation.yaml
-@$(YAMLLINT) .github/workflows/pypi.yaml
-@$(YAMLLINT) .github/workflows/test.yaml
-@$(YAMLLINT) .readthedocs.yaml
.PHONY: rst-check
rst-check: venv
-@$(RSTCHECK) README.rst
-@$(RSTCHECK) CHANGELOG.rst
-@$(RSTCHECK) $(DOCS_DIR)/index.rst
-@$(RSTCHECK) $(DOCS_DIR)/changelog.rst
-@$(RSTCHECK) --ignore-directives automodapi $(DOCS_DIR)/$(PACKAGE).rst
.PHONY: ruff-check
ruff-check: venv
$(RUFF) check
.PHONY: black-check
black-check: venv
$(BLACK) --check .
.PHONY: manifest-check
manifest-check: venv
$(CHECKMANIFEST)
.PHONY: pyroma-check
pyroma-check: venv
$(PYROMA) -d .
.PHONY: rcheck
rcheck:
@echo "Running all release checks..."
@$(MAKE) realclean
@$(MAKE) ruff-check
@$(MAKE) black-check
@$(MAKE) pylint-check
@$(MAKE) rst-check
@$(MAKE) manifest-check
@$(MAKE) pyroma-check
@$(MAKE) html
@$(MAKE) lite
@$(MAKE) dist
@$(MAKE) test
@$(MAKE) note-test
@echo "✅ Release checks complete"
.PHONY: lite
lite: venv $(LITE_CONFIG)
@echo "==> Building package wheel for PyOdide"
@$(PYTHON) -m build
@echo "==> Checking for .gh-pages worktree"
@if [ -d "$(WORKTREE)" ]; then \
echo " Found .gh-pages worktree, removing..."; \
git worktree remove "$(WORKTREE)" --force 2>/dev/null || true; \
git worktree prune; \
rm -rf "$(WORKTREE)"; \
echo " ✓ Removed"; \
else \
echo " No .gh-pages worktree found"; \
fi
@echo "==> Cleaning previous builds"
@/bin/rm -rf "$(OUT_ROOT)"
@/bin/rm -rf "$(DOIT_DB)"
@/bin/rm -rf ".doit.db"
@/bin/rm -rf ".jupyterlite.doit.db.db"
@echo " ✓ Cleaned"
@echo "==> Staging notebooks from docs -> $(STAGE_DIR)"
@/bin/rm -rf "$(STAGE_DIR)"; mkdir -p "$(STAGE_DIR)"
@if ls docs/*.ipynb 1> /dev/null 2>&1; then \
/bin/cp docs/*.ipynb "$(STAGE_DIR)"; \
echo "==> Clearing outputs from staged notebooks"; \
"$(PYTHON)" -m jupyter nbconvert --clear-output --inplace "$(STAGE_DIR)"/*.ipynb; \
else \
echo "⚠️ No notebooks found in docs/"; \
fi
@echo "==> Building JupyterLite"
@"$(PYTHON)" -m jupyter lite build \
--config="$(LITE_CONFIG)" \
--contents="$(STAGE_DIR)" \
--output-dir="$(OUT_DIR)"
@echo "==> Adding .nojekyll for GitHub Pages"
@touch "$(OUT_DIR)/.nojekyll"
@echo "✅ Build complete -> $(OUT_DIR)"
.PHONY: lite-serve
lite-serve: venv
@test -d "$(OUT_DIR)" || { echo "❌ run 'make lite' first"; exit 1; }
@echo "Serving at"
@echo " http://$(HOST):$(PORT)/$(PACKAGE)/?disableCache=1"
@echo ""
"$(PYTHON)" -m http.server -d "$(OUT_ROOT)" --bind $(HOST) $(PORT)
.PHONY: lite-deploy
lite-deploy:
@echo "==> Sanity check"
@test -d "$(OUT_DIR)" || { echo "❌ Run 'make lite' first"; exit 1; }
@echo "==> Ensure $(PAGES_BRANCH) branch exists"
@if ! git show-ref --verify --quiet refs/heads/$(PAGES_BRANCH); then \
CURRENT=$$(git branch --show-current); \
git switch --orphan $(PAGES_BRANCH); \
git commit --allow-empty -m "Initialize $(PAGES_BRANCH)"; \
git switch $$CURRENT; \
fi
@echo "==> Setup deployment worktree"
@git worktree remove "$(WORKTREE)" --force 2>/dev/null || true
@git worktree prune || true
@rm -rf "$(WORKTREE)"
@git worktree add "$(WORKTREE)" "$(PAGES_BRANCH)"
@git -C "$(WORKTREE)" pull "$(REMOTE)" "$(PAGES_BRANCH)" 2>/dev/null || true
@echo "==> Deploy $(OUT_DIR) -> $(WORKTREE)"
@rsync -a --delete --exclude ".git*" "$(OUT_DIR)/" "$(WORKTREE)/"
@touch "$(WORKTREE)/.nojekyll"
@date -u +"%Y-%m-%d %H:%M:%S UTC" > "$(WORKTREE)/.pages-ping"
@echo "==> Commit & push"
@cd "$(WORKTREE)" && \
git add -A && \
if git diff --quiet --cached; then \
echo "✅ No changes to deploy"; \
else \
git commit -m "Deploy $$(date -u +'%Y-%m-%d %H:%M:%S UTC')" && \
git push "$(REMOTE)" "$(PAGES_BRANCH)" && \
echo "✅ Deployed to https://$(GITHUB_USER).github.io/$(PACKAGE)/"; \
fi
.PHONY: clean
clean:
@echo "==> Cleaning build artifacts"
@find . -name '__pycache__' -type d -exec rm -rf {} +
@find . -name '.DS_Store' -type f -delete
@find . -name '.ipynb_checkpoints' -type d -prune -exec rm -rf {} +
@find . -name '.pytest_cache' -type d -prune -exec rm -rf {} +
rm -rf .cache
rm -rf .ruff_cache
rm -rf $(PACKAGE).egg-info
rm -rf docs/api
rm -rf docs/_build
rm -rf tests/charts
rm -rf dist
rm -rf build
.PHONY: lite-clean
lite-clean:
@echo "==> Cleaning JupyterLite build artifacts"
@/bin/rm -rf "$(STAGE_DIR)"
@/bin/rm -rf "$(OUT_ROOT)"
@/bin/rm -rf ".lite_root"
@/bin/rm -rf "$(DOIT_DB)"
@/bin/rm -rf "_output"
.PHONY: realclean
realclean: lite-clean clean
@echo "==> Deep cleaning: removing venv and deployment worktree"
@git worktree remove "$(WORKTREE)" --force 2>/dev/null || true
@/bin/rm -rf "$(WORKTREE)"
@/bin/rm -rf "$(VENV)"