argparse_neo(fix[renderer]): Namespace section names by id_prefix#16
argparse_neo(fix[renderer]): Namespace section names by id_prefix#16
Conversation
why: In multi-page MyST docs that embed .. argparse:: via {eval-rst},
docutils promotes section["names"] to cross-document explicit targets and
Sphinx's std domain flags every repeated implicit name as "duplicate
label". render_usage_section and render_group_section already namespaced
section["ids"] by id_prefix but hard-coded the unprefixed title into
section["names"], so every CLI page on vcspull/tmuxp/libtmux/... collided
on "usage", "options", "positional arguments". Fixes #15.
what:
- Mirror section["ids"] into section["names"] in render_usage_section
- Mirror section["ids"] into section["names"] in render_group_section
- Extend the existing doctests to assert the names/ids symmetry
- Add tests/ext/argparse_neo/test_renderer_section_names.py with unit
coverage for the with-prefix, without-prefix, and cross-page-disjoint
cases on both helpers
…efix
why: _create_example_section shares the same unscoped-names bug as
render_usage_section / render_group_section: section["ids"] was built
from section_id (which already includes the page prefix) but
section["names"] was hard-coded from the unprefixed section_title. In
MyST+{eval-rst} pages with multiple argparse directives, the implicit
"examples" target collided across pages. Fixes #15.
what:
- Mirror section["ids"] into section["names"] in _create_example_section
- Extend the existing doctests to assert the names/ids symmetry at both
the no-prefix and with-prefix call sites
…o duplicate-label warnings
why: The plain-RST multi-page build doesn't reproduce the
duplicate-label bug because Sphinx's std domain only flags explicit
hyperlink targets (see sphinx/domains/std/__init__.py:939), and plain
RST leaves argparse-neo's section["names"] as implicit targets. Embedding
the directive in a MyST {eval-rst} block — the pattern every downstream
consumer uses — promotes them to explicit cross-document targets, which
is what actually triggers the bug in vcspull/tmuxp/libtmux/etc. The
regression test needs to mirror that wiring or it silently passes on
broken code. Verified by reverting the two source commits locally: the
test fails with three duplicate labels (usage, positional arguments,
options). Gates #15.
what:
- Add tests/ext/argparse_neo/test_multi_page_integration.py with a
synthetic two-page MyST project that embeds .. argparse:: for two
distinct subcommand paths via {eval-rst}
- Assert zero "duplicate label" lines in the Sphinx warning buffer
- Snapshot and restore the "sphinx" logger state (propagate flag, level,
handlers) around the build; Sphinx.__init__ sets propagate=False and
attaches handlers that would otherwise leak into later caplog-based
tests in tests/ext/pytest_fixtures/
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #16 +/- ##
==========================================
+ Coverage 85.08% 86.12% +1.03%
==========================================
Files 95 97 +2
Lines 8509 8599 +90
==========================================
+ Hits 7240 7406 +166
+ Misses 1269 1193 -76 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Empirical validation against vcspull Installed
All 58 eliminated warnings belonged to the Remaining 6 stragglers — separate issue, out of scope for this PR The leftover 6 are all This PR stays scoped to the |
why: The hand-written section-names regression tests fanned out across two independent dimensions — renderer method (usage vs group) and prefix mode (none vs with-prefix). Collapsing them into parametrized cases makes the matrix obvious, matches gp-sphinx's NamedTuple + test_id convention from AGENTS.md, and keeps every assertion intact. what: - Factor _render_usage / _render_group helpers that take an id_prefix and return a docutils section, so parametrized cases can hold a Callable[[str], nodes.section] factory without branching inside the test body - Replace the per-method / per-prefix test functions with test_section_names_match_ids parametrized over SectionNameCase - Replace the two collision tests with test_multi_page_sections_do_not_collide parametrized over CollisionCase - Surface each case's identity as pytest ids (test_section_names_match_ids[usage-with-prefix] etc.) so failure messages stay as clear as the old function names
why: Capture the argparse-neo section-name scoping fix in the unreleased notes so the next gp-sphinx prerelease ships with a user-facing summary of the change. what: - Add a Bug fixes bullet under gp-sphinx 0.0.1 (unreleased) for the sphinx-argparse-neo render_usage_section / render_group_section / _create_example_section namespacing fix
why: Cut a new developmental release carrying the sphinx-argparse-neo multi-page duplicate-label fix (#16) so the 13 downstream consumers can pin a published prerelease instead of depending on unreleased main. what: - Raise project.version and internal == pins across pyproject.toml files - Bump __version__ and extension metadata strings - Update package_tools smoke conf, test_package_tools, and releasing docs examples - Regenerate uv.lock
Adopt the gp-sphinx Sphinx package stack for vcspull's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for cihai's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for cihai-cli's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for unihan-db's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for unihan-etl's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for libvcs's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for g's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for libtmux's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for tmuxp's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for libtmux-mcp's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **FastMCP autodoc** via sphinx-autodoc-fastmcp — card-style desc layouts for FastMCP tools, safety badges, MyST directives - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for gp-libs's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for django-docutils's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross-reference roles for Python objects, scoped section names in multi-page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Adopt the gp-sphinx Sphinx package stack for django-slugify- processor's API documentation. The net visual effect is card-style autodoc signatures with safety and scope badges, MyST cross- reference roles for Python objects, scoped section names in multi- page CLI docs, and polished IBM Plex typography — all landing together from the gp-sphinx 0.0.1a7 pre-release. - **API-style autodoc layout** via sphinx-autodoc-api-style — card layouts, badges, MyST roles for Python objects - **Shared badge layer** via sphinx-autodoc-badges — consistent XS/SM/LG/XL size variants with WCAG-AA contrast - **Multi-page argparse scoping** via sphinx-argparse-neo — CLI doc builds no longer emit duplicate-label warnings (git-pull/gp-sphinx#16) - **Font polish** via sphinx-fonts — IBM Plex Sans and Mono at full weight range, zero-CLS loading See gp-sphinx 0.0.1a7 release notes for the full list of changes covering 0.0.1a1..0.0.1a7: https://github.com/git-pull/gp-sphinx/blob/v0.0.1a7/CHANGES
Summary
section["ids"]intosection["names"]inrender_usage_section,render_group_section, and_create_example_sectionso multi-page MyST docs that embed.. argparse::via{eval-rst}no longer emitduplicate labelwarnings for shared implicit targets (usage,options,positional arguments,examples).mainand pass against this branch.Fixes #15.
Root cause
render_usage_section,render_group_section, and_create_example_sectionwere correctly namespacingsection["ids"]by the caller-suppliedid_prefixbut hard-coded the unprefixed title intosection["names"]:docutils turns
section["names"]into implicit hyperlink targets. On plain-RST pages those stay implicit and Sphinx's std domain silently dedupes them. But downstream consumers (vcspull, tmuxp, libtmux, libvcs, …) wire their CLI docs through MyST{eval-rst}blocks, which promote the nested RST section names to explicit cross-document targets. At that point Sphinx'sstd.process_doc(sphinx/domains/std/__init__.py:936-964) iteratesdocument.nametypes.items(),continues on implicit names, and logsduplicate label <name>, other instance in …for every collision of explicit names.Result: every CLI page on vcspull
api-stylingproduced one warning per shared section (usage,options,positional arguments), totalling 71 lines in a full build.Fix
Propagate
id_prefixintosection["names"]just like it already flows intosection["ids"]. The fix is a one-line change at each of three call sites — unit tests demonstrate thatsection["names"] == section["ids"]is now maintained under every combination of with/without prefix.Test plan
uv run ruff check . --fix --show-fixes— all checks passeduv run ruff format .— 110 files unchangeduv run mypy— no issues found in 105 source filesuv run py.test --reruns 0 -q— 783 passed, 3 skipped (776 baseline + 7 new)just build-docs— build succeeded, no new warningsRegression coverage, verified by locally reverting the two source commits:
tests/ext/argparse_neo/test_renderer_section_names.py— 5 of 6 unit tests fail on the old code (the sixth is a no-prefix baseline that happened to match trivially)tests/ext/argparse_neo/test_multi_page_integration.py— fails with three duplicate-label lines (usage,positional arguments,options); the test builds a synthetic MyST two-page project exactly mirroring the vcspull wiring patternDownstream impact
Thirteen repositories are currently on
api-stylingbranches consuming gp-sphinx 0.0.1a5/0.0.1a6. After this PR is merged and a new prerelease is cut, each of them gets a clean duplicate-label-free docs build via a single pin bump:Out of scope
vcspull's
api-stylingbuild also produces 39ERROR/3: Unexpected indentationlines duringreading sources.... Those are pre-existing onmasterin equal measure — they originate in a priority-ordering bug insphinx_autodoc_typehints/patches.py:75wherenapoleon_numpy_docstring_return_type_processor(registered atpriority=499) runs beforeprocess_docstring(atpriority=500), so typehints's own_inject_rtypeends up parsing a docstring that already contains its own:sentinel and docutils rejects the result. That belongs upstream attox-dev/sphinx-autodoc-typehints, and since future gp-sphinx releases are planned to dropsphinx.ext.napoleonandsphinx_autodoc_typehintsentirely, the noise will also disappear naturally — intentionally not addressed in this PR.Scope comparison for
vcspull:masterapi-stylingUnexpected indentationduplicate labelThis PR closes the
+7regression (and also zeroes out the pre-existing 64 as a bonus).Draft rationale
Marked as draft pending (a) CI validation across the supported Sphinx/Python matrix and (b) coordinated release + pin-bump across the 13 downstream repos listed above.