Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor auto-generate API docs #331

Merged
merged 8 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 14 additions & 37 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,55 +291,24 @@ All subsequent commands should be run from this directory.

To build the documentation, run:

::::{tab-set}
:::{tab-item} Unix platforms with `make`
```sh
make html
```
The local build can be viewed by opening `docs/build/html/index.html` in a browser.
:::

:::{tab-item} All platforms
```sh
python make_api_index.py && sphinx-build source build -W --keep-going
```
The local build can be viewed by opening `docs/build/index.html` in a browser.
:::
::::

To re-build the documentation after making changes, run the command below. It will remove all generated files in `docs/`,
including the auto-generated API index `source/api_index.rst`, and those in `build/`, `source/api/`, and `source/examples/`, and then re-build the documentation.
To re-build the documentation after making changes, we recommend removing existing build files first.
The following command will remove all generated files in `docs/`,
including the auto-generated API index `source/api_index.rst`, and those in `build/`, `source/api/`, and `source/examples/`. It will then re-build the documentation:

::::{tab-set}
:::{tab-item} Unix platforms with `make`
```sh
make clean html
```
:::

:::{tab-item} All platforms
```sh
rm -f source/api_index.rst && rm -rf build && rm -rf source/api && rm -rf source/examples
python make_api_index.py && sphinx-build source build -W --keep-going
```
:::
::::

To check that external links are correctly resolved, run:

::::{tab-set}
:::{tab-item} Unix platforms with `make`
```sh
make linkcheck
```
:::

:::{tab-item} All platforms
```sh
sphinx-build source build -b linkcheck -W --keep-going
```
:::
::::

If the linkcheck step incorrectly marks links with valid anchors as broken, you can skip checking the anchors in specific links by adding the URLs to `linkcheck_anchors_ignore_for_url` in `docs/source/conf.py`, e.g.:

Expand All @@ -352,6 +321,14 @@ linkcheck_anchors_ignore_for_url = [
]
```

:::{tip}
The `make` commands can be combined to run multiple tasks sequentially.
For example, to re-build the documentation and check the links, run:
```sh
make clean html linkcheck
```
:::

## Sample data

We maintain some sample datasets to be used for testing, examples and tutorials on an
Expand Down Expand Up @@ -399,9 +376,9 @@ To add a new file, you will need to:
6. Determine the sha256 checksum hash of each new file. You can do this in a terminal by running:
::::{tab-set}
:::{tab-item} Ubuntu
```bash
sha256sum <filename>
```
```bash
sha256sum <filename>
```
:::

:::{tab-item} MacOS
Expand Down
3 changes: 1 addition & 2 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
# You can set these variables from the command line, and also
# from the environment for the first two.
# -W: if there are warnings, treat them as errors and exit with status 1.
# --keep-going: run sphinx-build to completion and exit with status 1 if errors.
SPHINXOPTS ?= -W --keep-going
SPHINXOPTS ?= -W
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
Expand Down
19 changes: 16 additions & 3 deletions docs/make.bat
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ if "%SPHINXBUILD%" == "" (
)
set SOURCEDIR=source
set BUILDDIR=build
set SPHINXOPTS=-W

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
Expand All @@ -25,10 +26,22 @@ if errorlevel 9009 (

if "%1" == "" goto help

echo "Generating API index..."
python make_api_index.py
:process_targets
if "%1" == "clean" (
@echo Removing auto-generated files under 'docs' and 'src'...
rmdir /S /Q %BUILDDIR%
del /Q %SOURCEDIR%\api_index.rst
rmdir /S /Q %SOURCEDIR%\api\
rmdir /S /Q %SOURCEDIR%\examples\
) else (
@echo Generating API index...
python make_api_index.py
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
)

shift
if not "%1" == "" goto process_targets

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
Expand Down
37 changes: 15 additions & 22 deletions docs/make_api_index.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
"""Generate the API index page for all ``movement`` modules."""

import os
from pathlib import Path

# Modules to exclude from the API index
exclude_modules = ["cli_entrypoint"]

# Set the current working directory to the directory of this script
script_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = Path(__file__).resolve().parent
os.chdir(script_dir)


def make_api_index():
"""Create a doctree of all ``movement`` modules."""
doctree = "\n"

for root, _, files in os.walk("../movement"):
# Remove leading "../"
root = root[3:]
for file in sorted(files):
if file.endswith(".py") and not file.startswith("_"):
# Convert file path to module name
module_name = os.path.join(root, file)
module_name = module_name[:-3].replace(os.sep, ".")
# Check if the module should be excluded
if not any(
file.startswith(exclude_module)
for exclude_module in exclude_modules
):
doctree += f" {module_name}\n"

api_path = Path("../movement")
for path in sorted(api_path.rglob("*.py")):
if path.name.startswith("_"):
continue
# Convert file path to module name
rel_path = path.relative_to(api_path.parent)
module_name = str(rel_path.with_suffix("")).replace(os.sep, ".")
if rel_path.stem not in exclude_modules:
doctree += f" {module_name}\n"
# Get the header
with open("./source/_templates/api_index_head.rst") as f:
api_head = f.read()
api_head_path = Path("source") / "_templates" / "api_index_head.rst"
api_head = api_head_path.read_text()
# Write api_index.rst with header + doctree
with open("./source/api_index.rst", "w") as f:
f.write("..\n This file is auto-generated.\n\n")
output_path = Path("source") / "api_index.rst"
with output_path.open("w") as f:
f.write(api_head)
f.write(doctree)
print(os.path.abspath("./source/api_index.rst"))


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ myst-parser
nbsphinx
pydata-sphinx-theme
setuptools-scm
sphinx>=7.0
sphinx
sphinx-autodoc-typehints
sphinx-design
sphinx-gallery
Expand Down
3 changes: 3 additions & 0 deletions docs/source/_templates/api_index_head.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
..
This file is auto-generated.

.. _target-api:

API Reference
Expand Down
Loading