From 55d2f067ba9fcd947c3ed001703fbe06222b0156 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 28 Nov 2022 16:50:27 -0800 Subject: [PATCH 1/2] Proof-of-concept `doc` command --- .github/workflows/test.yml | 2 ++ README.md | 2 +- devpy/cmds/__init__.py | 1 + devpy/cmds/_doc.py | 39 ++++++++++++++++++++++++++++++++ devpy/cmds/util.py | 4 +++- example_pkg/doc/.gitignore | 1 + example_pkg/doc/Makefile | 20 ++++++++++++++++ example_pkg/doc/conf.py | 26 +++++++++++++++++++++ example_pkg/doc/index.md | 4 ++++ example_pkg/doc/make.bat | 35 ++++++++++++++++++++++++++++ example_pkg/doc/requirements.txt | 3 +++ example_pkg/pyproject.toml | 1 + pyproject.toml | 17 -------------- 13 files changed, 136 insertions(+), 19 deletions(-) create mode 100644 devpy/cmds/_doc.py create mode 100644 example_pkg/doc/.gitignore create mode 100644 example_pkg/doc/Makefile create mode 100644 example_pkg/doc/conf.py create mode 100644 example_pkg/doc/index.md create mode 100644 example_pkg/doc/make.bat create mode 100644 example_pkg/doc/requirements.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index baca50c..860b1d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,6 +26,7 @@ jobs: run: | pip install -e . pip install pytest meson-python ninja + pip install -r example_pkg/doc/requirements.txt - name: Test shell: 'script -q -e -c "bash --noprofile --norc -eo pipefail {0}"' env: @@ -34,3 +35,4 @@ jobs: cd example_pkg ./dev.py build ./dev.py test + ./dev.py doc diff --git a/README.md b/README.md index 676483d..745054a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Typically, their lives are made simpler by a Makefile, but Makefiles can be conv The rationale behind `devpy` is therefore to provide a simple interface for common development tasks. It comes with a few common build commands out the box, but can easily be customized per project. -As a curiosity: the impetus behind developing the tool was the mass migration of scientific Python libraries (SciPy, scikit-image, and NumPy, etc.) to Meson, after distutils was deprecated. +As a curiosity: the impetus behind developing the tool was the mass migration of scientific Python libraries (SciPy, scikit-image, and NumPy, etc.) to [Meson](https://mesonbuild.com/), after `distutils` was deprecated. When many of the build and installation commands changed, it made sense to abstract away the nuisance of having to re-learn them. ## Configuration diff --git a/devpy/cmds/__init__.py b/devpy/cmds/__init__.py index e8845ce..c0e3569 100644 --- a/devpy/cmds/__init__.py +++ b/devpy/cmds/__init__.py @@ -1,3 +1,4 @@ from ._build import build from ._test import test from ._shell import ipython, python, shell +from ._doc import doc diff --git a/devpy/cmds/_doc.py b/devpy/cmds/_doc.py new file mode 100644 index 0000000..bf50d3a --- /dev/null +++ b/devpy/cmds/_doc.py @@ -0,0 +1,39 @@ +import sys +import os + +import click + +from . import util + + +@click.command() +@click.option( + "--build-dir", default="build", help="Build directory; default is `$PWD/build`" +) +@click.option( + "--clean", is_flag=True, help="Clean previously built docs before building" +) +@click.argument("targets", required=False, nargs=-1) +def doc(build_dir, targets, clean=False): + """📖 Build documentation + + Set the PYTHONPATH to the build path, and invoke `make` in the + `doc` directory. + + For a list of Sphinx make targets: + + ./dev.py doc help + """ + if not targets: + targets = ["html"] + if clean: + doc_dir = "./doc/build" + if os.path.isdir(doc_dir): + print(f"Removing `{doc_dir}`") + shutil.rmtree(doc_dir) + + util.set_pythonpath(build_dir) + + print("$ export SPHINXOPTS='-W'") + os.environ["SPHINXOPTS"] = "-W" + util.run(["make", "-C", "doc"] + list(targets), replace=True) diff --git a/devpy/cmds/util.py b/devpy/cmds/util.py index 504d441..df5f061 100644 --- a/devpy/cmds/util.py +++ b/devpy/cmds/util.py @@ -45,7 +45,9 @@ def get_site_packages(build_dir): def set_pythonpath(build_dir): site_packages = get_site_packages(build_dir) if site_packages is None: - print(f"No `site-packages` directory found under {build_dir}; aborting") + print( + f"No `site-packages` directory found under {install_dir(build_dir)}; run `./dev.py build` first" + ) sys.exit(1) env = os.environ diff --git a/example_pkg/doc/.gitignore b/example_pkg/doc/.gitignore new file mode 100644 index 0000000..e35d885 --- /dev/null +++ b/example_pkg/doc/.gitignore @@ -0,0 +1 @@ +_build diff --git a/example_pkg/doc/Makefile b/example_pkg/doc/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/example_pkg/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/example_pkg/doc/conf.py b/example_pkg/doc/conf.py new file mode 100644 index 0000000..9a7c126 --- /dev/null +++ b/example_pkg/doc/conf.py @@ -0,0 +1,26 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "devpy" +copyright = "2022, The Scientific Python developers" +author = "The Scientific Python developers" + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ["myst_parser"] + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "pydata_sphinx_theme" +html_static_path = ["_static"] diff --git a/example_pkg/doc/index.md b/example_pkg/doc/index.md new file mode 100644 index 0000000..ea6b708 --- /dev/null +++ b/example_pkg/doc/index.md @@ -0,0 +1,4 @@ +# devpy example package + +This example package is used to test `devpy` with. +It contains one Python extension, namely `example_pkg.echo`. diff --git a/example_pkg/doc/make.bat b/example_pkg/doc/make.bat new file mode 100644 index 0000000..954237b --- /dev/null +++ b/example_pkg/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/example_pkg/doc/requirements.txt b/example_pkg/doc/requirements.txt new file mode 100644 index 0000000..5a0d590 --- /dev/null +++ b/example_pkg/doc/requirements.txt @@ -0,0 +1,3 @@ +sphinx +myst-parser +pydata-sphinx-theme diff --git a/example_pkg/pyproject.toml b/example_pkg/pyproject.toml index de6f21b..c340520 100644 --- a/example_pkg/pyproject.toml +++ b/example_pkg/pyproject.toml @@ -14,4 +14,5 @@ package = 'example_pkg' "Build" = ["devpy.build", "devpy.test"] "Environments" = ["devpy.shell", "devpy.ipython", "devpy.python"] +"Documentation" = ["devpy.doc"] "Extensions" = [".devpy/cmds.py:example"] diff --git a/pyproject.toml b/pyproject.toml index c2af3a0..953f4b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,20 +25,3 @@ homepage = "https://github.com/scientific-python/devpy" [tool.setuptools.packages.find] include = ["devpy*"] - -[tool.pytest.ini_options] -filterwarnings = [ - "ignore:cannot collect 'test' because it is not a function:", -] - -[tool.devpy] -package = 'devpy' - -[tool.devpy.commands] -# If you don't need sections, you can also provide a list of commands under [tool.devpy]: -# -# commands = ["devpy.build", "devpy.test", "devpy.shell", "devpy.ipython", "devpy.python", "custom/cmds.py:example"] - -"Build" = ["devpy.build", "devpy.test"] -"Environments" = ["devpy.shell", "devpy.ipython", "devpy.python"] -"Extensions" = ["example_pkg/.devpy/cmds.py:example"] From 0850d403790ae1d8b9882b824fed7c55d8969eb6 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Tue, 29 Nov 2022 10:50:48 -0800 Subject: [PATCH 2/2] Commit _static and _templates directories --- example_pkg/doc/_static/.gitkeep | 0 example_pkg/doc/_templates/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 example_pkg/doc/_static/.gitkeep create mode 100644 example_pkg/doc/_templates/.gitkeep diff --git a/example_pkg/doc/_static/.gitkeep b/example_pkg/doc/_static/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/example_pkg/doc/_templates/.gitkeep b/example_pkg/doc/_templates/.gitkeep new file mode 100644 index 0000000..e69de29