Skip to content

Commit e2c74fd

Browse files
committed
refactor(workspace): Split into 4 UV workspace packages
why: Separate concerns into independently versioned, reusable packages. sphinx-argparse-neo and sphinx-fonts are generic (no git-pull branding). sphinx-gptheme is the visual identity. gp-sphinx coordinates them. what: - Create UV workspace: packages/{sphinx-argparse-neo,sphinx-gptheme, sphinx-fonts,gp-sphinx} each with own pyproject.toml and src layout - sphinx-argparse-neo: standalone argparse CLI doc extension (import sphinx_argparse_neo) - sphinx-gptheme: Furo child theme (html_theme = "sphinx-gptheme") - sphinx-fonts: Fontsource CDN font extension (import sphinx_fonts) - gp-sphinx: config coordinator (merge_sphinx_config, make_linkcode_resolve) depends on the other 3, optional dep on sphinx-argparse-neo - Root pyproject.toml: workspace config, shared tool settings - Fix all imports across source, tests, and docs - Remove old src/gp_sphinx/ (code moved to packages/) - Tests: 410 passing
1 parent f3424fd commit e2c74fd

54 files changed

Lines changed: 517 additions & 628 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/conf.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import pathlib
66
import sys
77

8-
# Bootstrap: allow importing local package during development
8+
# Bootstrap: allow importing workspace packages during development
99
cwd = pathlib.Path(__file__).parent
1010
project_root = cwd.parent
11-
sys.path.insert(0, str(project_root / "src"))
11+
sys.path.insert(0, str(project_root / "packages" / "gp-sphinx" / "src"))
12+
sys.path.insert(0, str(project_root / "packages" / "sphinx-fonts" / "src"))
13+
sys.path.insert(0, str(project_root / "packages" / "sphinx-gptheme" / "src"))
1214

1315
import gp_sphinx # noqa: E402
1416
from gp_sphinx.config import merge_sphinx_config # noqa: E402

packages/gp-sphinx/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# gp-sphinx · [![Python Package](https://img.shields.io/pypi/v/gp-sphinx.svg)](https://pypi.org/project/gp-sphinx/) [![License](https://img.shields.io/github/license/git-pull/gp-sphinx.svg)](https://github.com/git-pull/gp-sphinx/blob/master/LICENSE)
2+
3+
Shared Sphinx documentation platform for [git-pull](https://github.com/git-pull) projects.
4+
5+
Consolidates duplicated docs configuration, extensions, theme settings, and workarounds from 14+ repositories into a single reusable package.
6+
7+
## Install
8+
9+
```console
10+
$ pip install gp-sphinx
11+
```
12+
13+
```console
14+
$ uv add gp-sphinx
15+
```
16+
17+
## Usage
18+
19+
Replace ~300 lines of duplicated `docs/conf.py` with ~10 lines:
20+
21+
```python
22+
"""Sphinx configuration for my-project."""
23+
from __future__ import annotations
24+
25+
from gp_sphinx.config import merge_sphinx_config
26+
27+
import my_project
28+
29+
conf = merge_sphinx_config(
30+
project="my-project",
31+
version=my_project.__version__,
32+
copyright="2026, Tony Narlock",
33+
source_repository="https://github.com/git-pull/my-project/",
34+
intersphinx_mapping={
35+
"py": ("https://docs.python.org/", None),
36+
},
37+
)
38+
globals().update(conf)
39+
```
40+
41+
## Features
42+
43+
- `merge_sphinx_config()` API for shared defaults with per-project overrides
44+
- Shared extension list (autodoc, intersphinx, myst_parser, sphinx_design, etc.)
45+
- Shared Furo theme configuration (CSS variables, fonts, sidebar, footer)
46+
- Bundled workarounds (tabs.js removal, spa-nav.js injection)
47+
- Shared font configuration (IBM Plex via Fontsource)
48+
49+
## More information
50+
51+
- Documentation: <https://gp-sphinx.git-pull.com>
52+
- Source: <https://github.com/git-pull/gp-sphinx>
53+
- Changelog: <https://github.com/git-pull/gp-sphinx/blob/master/CHANGES>
54+
- Issues: <https://github.com/git-pull/gp-sphinx/issues>
55+
- PyPI: <https://pypi.org/project/gp-sphinx/>
56+
- License: [MIT](https://github.com/git-pull/gp-sphinx/blob/master/LICENSE)

packages/gp-sphinx/pyproject.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[project]
2+
name = "gp-sphinx"
3+
version = "0.0.1"
4+
description = "Shared Sphinx documentation platform for git-pull projects"
5+
requires-python = ">=3.10,<4.0"
6+
authors = [
7+
{name = "Tony Narlock", email = "tony@git-pull.com"}
8+
]
9+
license = { text = "MIT" }
10+
classifiers = [
11+
"Development Status :: 3 - Alpha",
12+
"License :: OSI Approved :: MIT License",
13+
"Framework :: Sphinx",
14+
"Intended Audience :: Developers",
15+
"Programming Language :: Python :: 3",
16+
"Programming Language :: Python :: 3.10",
17+
"Programming Language :: Python :: 3.11",
18+
"Programming Language :: Python :: 3.12",
19+
"Programming Language :: Python :: 3.13",
20+
"Programming Language :: Python :: 3.14",
21+
"Topic :: Documentation",
22+
"Topic :: Documentation :: Sphinx",
23+
]
24+
readme = "README.md"
25+
keywords = ["sphinx", "documentation", "configuration"]
26+
dependencies = [
27+
"sphinx<9",
28+
"sphinx-gptheme",
29+
"sphinx-fonts",
30+
"myst-parser",
31+
"docutils",
32+
"sphinx-autodoc-typehints",
33+
"sphinx-inline-tabs",
34+
"sphinx-copybutton",
35+
"sphinxext-opengraph",
36+
"sphinxext-rediraffe",
37+
"sphinx-design",
38+
"linkify-it-py",
39+
"gp-libs",
40+
]
41+
42+
[project.optional-dependencies]
43+
argparse = [
44+
"sphinx-argparse-neo",
45+
]
46+
47+
[project.urls]
48+
"Bug Tracker" = "https://github.com/git-pull/gp-sphinx/issues"
49+
Documentation = "https://gp-sphinx.git-pull.com"
50+
Repository = "https://github.com/git-pull/gp-sphinx"
51+
Changes = "https://github.com/git-pull/gp-sphinx/blob/master/CHANGES"
52+
53+
[build-system]
54+
requires = ["hatchling"]
55+
build-backend = "hatchling.build"
56+
57+
[tool.hatch.build.targets.wheel]
58+
packages = ["src/gp_sphinx"]
File renamed without changes.
File renamed without changes.

src/gp_sphinx/config.py renamed to packages/gp-sphinx/src/gp_sphinx/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
'my-project'
1818
1919
>>> conf["html_theme"]
20-
'gp-sphinx'
20+
'sphinx-gptheme'
2121
2222
>>> "myst_parser" in conf["extensions"]
2323
True
@@ -285,7 +285,7 @@ def merge_sphinx_config(
285285
'1.0'
286286
287287
>>> conf["html_theme"]
288-
'gp-sphinx'
288+
'sphinx-gptheme'
289289
290290
>>> len(conf["extensions"]) >= 13
291291
True

src/gp_sphinx/defaults.py renamed to packages/gp-sphinx/src/gp_sphinx/defaults.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
DEFAULT_EXTENSIONS: list[str] = [
4040
"sphinx.ext.autodoc",
41-
"gp_sphinx.sphinx_fonts",
41+
"sphinx_fonts",
4242
"sphinx.ext.intersphinx",
4343
"sphinx_autodoc_typehints",
4444
"sphinx.ext.todo",
@@ -62,7 +62,7 @@
6262
'sphinx.ext.autodoc'
6363
"""
6464

65-
DEFAULT_THEME: str = "gp-sphinx"
65+
DEFAULT_THEME: str = "sphinx-gptheme"
6666
"""Default Sphinx HTML theme (Furo child theme bundled in this package)."""
6767

6868
DEFAULT_THEME_OPTIONS: dict[str, t.Any] = {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# sphinx-argparse-neo
2+
3+
Modern Sphinx extension for documenting argparse-based CLI tools.
4+
5+
A modernized replacement for `sphinx-argparse` that:
6+
- Works with Sphinx 8.x and 9.x (no `autodoc.mock` dependency)
7+
- Fixes long-standing issues (TOC pollution, heading levels)
8+
- Provides configurable output (rubrics vs sections, flattened subcommands)
9+
- Includes Pygments lexers for argparse help output and CLI usage blocks
10+
- Supports extensibility via renderer classes
11+
12+
## Install
13+
14+
```console
15+
$ pip install sphinx-argparse-neo
16+
```
17+
18+
## Usage
19+
20+
In your `docs/conf.py`:
21+
22+
```python
23+
extensions = ["sphinx_argparse_neo"]
24+
```
25+
26+
Then use the `.. argparse::` directive:
27+
28+
```rst
29+
.. argparse::
30+
:module: myapp.cli
31+
:func: create_parser
32+
:prog: myapp
33+
```
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[project]
2+
name = "sphinx-argparse-neo"
3+
version = "0.1.0"
4+
description = "Modern Sphinx extension for documenting argparse-based CLI tools"
5+
requires-python = ">=3.10,<4.0"
6+
authors = [
7+
{name = "Tony Narlock", email = "tony@git-pull.com"}
8+
]
9+
license = { text = "MIT" }
10+
classifiers = [
11+
"Development Status :: 4 - Beta",
12+
"License :: OSI Approved :: MIT License",
13+
"Framework :: Sphinx",
14+
"Framework :: Sphinx :: Extension",
15+
"Intended Audience :: Developers",
16+
"Programming Language :: Python :: 3",
17+
"Programming Language :: Python :: 3.10",
18+
"Programming Language :: Python :: 3.11",
19+
"Programming Language :: Python :: 3.12",
20+
"Programming Language :: Python :: 3.13",
21+
"Programming Language :: Python :: 3.14",
22+
"Topic :: Documentation",
23+
"Topic :: Documentation :: Sphinx",
24+
"Topic :: Software Development :: Documentation",
25+
]
26+
readme = "README.md"
27+
keywords = ["sphinx", "argparse", "cli", "documentation"]
28+
dependencies = [
29+
"sphinx",
30+
"pygments",
31+
"docutils",
32+
]
33+
34+
[project.urls]
35+
Repository = "https://github.com/git-pull/gp-sphinx"
36+
37+
[build-system]
38+
requires = ["hatchling"]
39+
build-backend = "hatchling.build"
40+
41+
[tool.hatch.build.targets.wheel]
42+
packages = ["src/sphinx_argparse_neo"]

src/gp_sphinx/ext/argparse/neo/__init__.py renamed to packages/sphinx-argparse-neo/src/sphinx_argparse_neo/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
import typing as t
1414

15-
from gp_sphinx.ext.argparse.neo.directive import ArgparseDirective
16-
from gp_sphinx.ext.argparse.neo.nodes import (
15+
from sphinx_argparse_neo.directive import ArgparseDirective
16+
from sphinx_argparse_neo.nodes import (
1717
argparse_argument,
1818
argparse_group,
1919
argparse_program,
@@ -33,7 +33,7 @@
3333
visit_argparse_subcommands_html,
3434
visit_argparse_usage_html,
3535
)
36-
from gp_sphinx.ext.argparse.neo.utils import strip_ansi
36+
from sphinx_argparse_neo.utils import strip_ansi
3737

3838
__all__ = [
3939
"ArgparseDirective",

0 commit comments

Comments
 (0)