diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 32ec2f6..45e8dbf 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -27,11 +27,11 @@ jobs: pre-build: uv run python docs/tools/examples.py smoke-paths: | getting-started/installation/index.html - tutorials/index.html - tutorials/example-tutorial/index.html - full-examples/index.html - full-examples/sine-wave/index.html + examples/index.html + examples/example-tutorial/index.html + example-scripts/index.html + example-scripts/sine-wave/index.html api/app/index.html api/app/main/index.html - tutorials/example-tutorial/example_tutorial.ipynb - full-examples/sine-wave/plot-1.png + examples/example-tutorial/example_tutorial.ipynb + example-scripts/sine-wave/plot-1.png diff --git a/Makefile b/Makefile index acbf9bd..7b6dc6f 100644 --- a/Makefile +++ b/Makefile @@ -34,11 +34,11 @@ docs-install: ## Python docs extra and the npm packages $(PYTHON) -m pip install -e ".[docs]" cd docs && npm ci -docs-notebooks: ## execute the changed tutorials and convert all of them (FORCE=1 reruns all) +docs-notebooks: ## execute the changed notebooks and convert all of them (FORCE=1 reruns all) $(NOTEBOOKS) execute $(if $(FORCE),--force,) $(NOTEBOOKS) convert -docs-examples: ## run full Python examples and generate pages with their plots +docs-examples: ## run the example scripts and generate pages with their plots $(PYTHON) docs/tools/examples.py docs-dev: ## live preview at http://localhost:4321/template-python/ @@ -56,5 +56,5 @@ docs-preview: ## serve docs/dist docs-clean: ## remove generated pages, assets and build output $(NOTEBOOKS) clean - rm -rf docs/src/content/docs/full-examples docs/public/full-examples + rm -rf docs/src/content/docs/example-scripts docs/public/example-scripts rm -rf docs/dist docs/.astro diff --git a/README.md b/README.md index f424113..e520db5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ analysis](https://github.com/max-models/template-python/actions/workflows/static Template repository for Python projects: a `src/` package with a console entry point, `pytest` tests, GitHub Actions for tests, static analysis, -tutorials, documentation and PyPI publishing, and an +example notebooks, documentation and PyPI publishing, and an [Astro](https://astro.build/) + [Starlight](https://starlight.astro.build/) documentation site. diff --git a/README.qmd b/README.qmd index 54224af..b011004 100644 --- a/README.qmd +++ b/README.qmd @@ -16,7 +16,7 @@ format: [![Python](https://img.shields.io/pypi/pyversions/template-python)](https://pypi.org/project/template-python/) Template repository for Python projects: a `src/` package with a console entry point, -`pytest` tests, GitHub Actions for tests, static analysis, tutorials, documentation and +`pytest` tests, GitHub Actions for tests, static analysis, example notebooks, documentation and PyPI publishing, and an [Astro](https://astro.build/) + [Starlight](https://starlight.astro.build/) documentation site. diff --git a/docs/.gitignore b/docs/.gitignore index 4e58606..8955814 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -4,7 +4,7 @@ dist/ node_modules/ # generated by starlight-notebooks (regenerated in CI) .cache/ -public/tutorials/ -src/content/docs/tutorials/*.mdx -public/full-examples/ -src/content/docs/full-examples/ +public/examples/ +src/content/docs/examples/*.mdx +public/example-scripts/ +src/content/docs/example-scripts/ diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 2a189da..a3642b7 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -10,8 +10,7 @@ export default defineDocs({ pythonPackage: 'app', nav: [ { label: 'Getting started', link: '/getting-started/installation/' }, - { label: 'Tutorials', link: '/tutorials/' }, - { label: 'Full examples', link: '/full-examples/' }, + { label: 'Examples', link: '/examples/' }, { label: 'Development', link: '/development/docs/' }, { label: 'API', link: '/api/app/' }, ], @@ -24,12 +23,11 @@ export default defineDocs({ ], }, { - label: 'Tutorials', - items: [{ autogenerate: { directory: 'tutorials' } }], - }, - { - label: 'Full examples', - items: [{ autogenerate: { directory: 'full-examples' } }], + label: 'Examples', + items: [ + { autogenerate: { directory: 'examples' } }, + { label: 'Scripts', items: [{ autogenerate: { directory: 'example-scripts' } }] }, + ], }, { label: 'Development', diff --git a/docs/package.json b/docs/package.json index 4c08adf..837717c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -20,5 +20,8 @@ "@max-models/starlight-theme": "github:max-models/starlight-theme#v0.6.0", "astro": "^7.4.0", "sharp": "^0.35.3" + }, + "starlight-notebooks": { + "section": "examples" } } diff --git a/docs/public/tutorials/example-tutorial/example_tutorial.ipynb b/docs/public/tutorials/example-tutorial/example_tutorial.ipynb deleted file mode 100644 index a48ed6a..0000000 --- a/docs/public/tutorials/example-tutorial/example_tutorial.ipynb +++ /dev/null @@ -1,45 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "0", - "metadata": {}, - "source": [ - "# Example guide\n", - "\n", - "Run a small example and view its output." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1", - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Example guide published in the docs!\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/src/content/docs/development/docs.md b/docs/src/content/docs/development/docs.md index a915c87..ab720d1 100644 --- a/docs/src/content/docs/development/docs.md +++ b/docs/src/content/docs/development/docs.md @@ -1,19 +1,24 @@ --- title: Building the docs -description: How this documentation site is built from Markdown pages, Jupyter tutorials and docstrings. +description: How this documentation site is built from Markdown pages, Jupyter notebooks and docstrings. --- The site in `docs/` is built with [Astro](https://astro.build/) and [Starlight](https://starlight.astro.build/). It has three kinds of pages: - **Hand-written pages** in `docs/src/content/docs/`, as Markdown or MDX. -- **Tutorials**, converted from the Jupyter notebooks in `tutorials/` by `starlight-notebooks`. - Each notebook is executed and its outputs (text, images, tables) are written into an MDX page. -- **Full examples**, built from Python scripts in `examples/` by `docs/tools/examples.py`. - Each page shows the module docstring, the complete source file, and its Matplotlib plots. +- **Examples**, converted from the Jupyter notebooks in `tutorials/` by `starlight-notebooks` + (the `section` setting in `docs/package.json` publishes them under `examples/`). Each + notebook is executed and its outputs (text, images, tables) are written into an MDX page. +- **Example scripts**, a "Scripts" group of the Examples, built from the Python scripts in + `examples/` by `docs/tools/examples.py`. Each page shows the module docstring, the complete + source file, and its Matplotlib plots. - **API reference**, generated from the docstrings by [starlight-pydocs](https://ewels.github.io/starlight-pydocs/), one page per module. +Guides, when a project has them, are hand-written pages that explain the model or a concept; +anything runnable belongs in the Examples. + The configuration (`defineDocs` in `docs/astro.config.mjs`), the look, the header, the notebook tool and the build workflow come from the shared [starlight-theme](https://github.com/max-models/starlight-theme) of the max-models projects; @@ -40,9 +45,9 @@ make docs-clean # remove generated pages and build output `make docs-notebooks` only reruns a notebook whose cells changed since the last run; pass `FORCE=1` to rerun all of them. -## Writing tutorials +## Writing example notebooks -Put a Jupyter notebook in `tutorials/`. Tutorials are authored only as `.ipynb` files. Its first `# Heading` becomes the page title and the first +Put a Jupyter notebook in `tutorials/`. Examples are authored only as `.ipynb` files. Its first `# Heading` becomes the page title and the first paragraph its description. Cell tags control the output: | Tag | Effect | @@ -55,7 +60,7 @@ paragraph its description. Cell tags control the output: Math in `$...$` and `$$...$$` is rendered with KaTeX. -## Writing full examples +## Writing example scripts Put a Python script in `examples/` with a module docstring. Its first line becomes the page title and the rest becomes the description. Leave Matplotlib figures open at the end of the diff --git a/docs/src/content/docs/development/publishing.md b/docs/src/content/docs/development/publishing.md index 76e37b8..b22aefe 100644 --- a/docs/src/content/docs/development/publishing.md +++ b/docs/src/content/docs/development/publishing.md @@ -6,7 +6,7 @@ description: Publish the package to PyPI and the documentation to GitHub Pages. ## Documentation The `Docs` workflow builds the site on every push and pull request to `main` and `devel`. It -executes the tutorials, generates the API reference and uploads the site. Pushes to `devel` +executes the notebooks, generates the API reference and uploads the site. Pushes to `devel` also deploy it to GitHub Pages at https://max-models.github.io/template-python/. Enable GitHub Pages once in the repository settings, with "GitHub Actions" as the source. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index a10c6b0..b366631 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -3,7 +3,7 @@ title: template-python description: Template repository for Python projects. template: splash hero: - tagline: A starting point for a Python package with tests, CI, tutorials and an Astro documentation site. + tagline: A starting point for a Python package with tests, CI, examples and an Astro documentation site. actions: - text: Get started link: /template-python/getting-started/installation/ @@ -23,13 +23,11 @@ import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; A `src/` layout with a console entry point, `pytest` tests and a `pyproject.toml` ready for PyPI. - GitHub Actions for tests, static analysis, tutorial execution, documentation and PyPI publishing. + GitHub Actions for tests, static analysis, notebook execution, documentation and PyPI publishing. - - Jupyter notebooks in `tutorials/` are executed and published as pages of this site. - - - Complete Python scripts in `examples/` are shown with their plots. + + Jupyter notebooks in `tutorials/` are executed and published as pages of this site, and + complete Python scripts in `examples/` are shown with their plots. Every module, class and function is documented from the docstrings with starlight-pydocs. @@ -41,7 +39,6 @@ import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; - - + diff --git a/docs/src/content/docs/tutorials/example-tutorial.mdx b/docs/src/content/docs/tutorials/example-tutorial.mdx deleted file mode 100644 index 96c4764..0000000 --- a/docs/src/content/docs/tutorials/example-tutorial.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Example guide" -description: "Run a small example and view its output." -sidebar: - order: 2 ---- - -import NotebookHeader from '@max-models/starlight-theme/components/NotebookHeader.astro'; - - - -Run a small example and view its output. - -```python -print("Example guide published in the docs!") -``` - -```text -Example guide published in the docs! -``` diff --git a/docs/tools/examples.py b/docs/tools/examples.py index 6c6dda4..3dc3b2e 100644 --- a/docs/tools/examples.py +++ b/docs/tools/examples.py @@ -1,4 +1,4 @@ -"""Build Full examples pages from Python scripts and their Matplotlib figures.""" +"""Build the example script pages from Python scripts and their Matplotlib figures.""" from __future__ import annotations @@ -21,8 +21,9 @@ ROOT = DOCS.parent SOURCES = ROOT / "examples" -CONTENT = DOCS / "src" / "content" / "docs" / "full-examples" -PUBLIC = DOCS / "public" / "full-examples" +# the "Scripts" group of the Examples section, next to the notebook pages in examples/ +CONTENT = DOCS / "src" / "content" / "docs" / "example-scripts" +PUBLIC = DOCS / "public" / "example-scripts" def source_fence(code: str) -> str: @@ -64,7 +65,7 @@ def build_example(source: Path, order: int) -> tuple[str, str]: filename = f"plot-{index}.png" plt.figure(number).savefig(output / filename, dpi=150, bbox_inches="tight") plots.append( - f"![Plot {index} from {title}](/template-python/full-examples/{slug}/{filename})" + f"![Plot {index} from {title}](/template-python/example-scripts/{slug}/{filename})" ) plt.close("all") page = [ @@ -92,7 +93,7 @@ def build_example(source: Path, order: int) -> tuple[str, str]: def main() -> None: - """Regenerate all Full examples pages and assets.""" + """Regenerate all example script pages and assets.""" shutil.rmtree(CONTENT, ignore_errors=True) shutil.rmtree(PUBLIC, ignore_errors=True) examples = sorted(SOURCES.glob("*.py")) @@ -101,14 +102,14 @@ def main() -> None: title, summary = build_example(source, order) slug = re.sub(r"[^a-z0-9]+", "-", source.stem.lower()).strip("-") listing.append( - f"- [{title}](/template-python/full-examples/{slug}/): {summary}" + f"- [{title}](/template-python/example-scripts/{slug}/): {summary}" ) print(f"[examples] {source} -> {CONTENT / slug}.mdx") CONTENT.mkdir(parents=True, exist_ok=True) (CONTENT / "index.md").write_text( - "---\ntitle: Full examples\ndescription: Complete Python scripts and their plots.\n" + "---\ntitle: Scripts\ndescription: Complete Python scripts and their plots.\n" "sidebar:\n order: 0\n---\n\n" - "Complete Python examples are listed below. Each page shows the script and its plots.\n\n" + "Complete Python scripts are listed below. Each page shows the script and its plots.\n\n" + "\n".join(listing) + "\n" ) diff --git a/tutorials/index.ipynb b/tutorials/index.ipynb index 4590a40..ed2407e 100644 --- a/tutorials/index.ipynb +++ b/tutorials/index.ipynb @@ -5,12 +5,13 @@ "id": "0", "metadata": {}, "source": [ - "# Tutorials\n", + "# Examples\n", "\n", "Jupyter notebooks in this section are executed when the documentation is built. Download a notebook from its page to run it yourself.\n", "\n", - "- [Example tutorial](/template-python/tutorials/example-tutorial/) runs a small Python example.\n", - "- [Building the docs](/template-python/development/docs/) explains how to add a tutorial and control its output.\n" + "- [Example notebook](/template-python/examples/example-tutorial/) runs a small Python example.\n", + "- [Scripts](/template-python/example-scripts/) are complete Python scripts with their plots.\n", + "- [Building the docs](/template-python/development/docs/) explains how to add an example and control its output.\n" ] } ],