Skip to content

fix(docs): stop AppType shadowing six builtins in cross-references - #724

Closed
JarryShaw wants to merge 1 commit into
mainfrom
fix/717-dict-rst-type-xref
Closed

JarryShaw wants to merge 1 commit into
mainfrom
fix/717-dict-rst-type-xref

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Sep 23, 2026

Copy link
Copy Markdown
Owner
  • Searched for similar pull requests
  • Followed the coding style (docs-only change, no .py touched)
  • make test passes, and a test case covers the change
  • Added a changelog entry under docs/source/changelog/

What is the purpose of your pull request?

  • docs

Description of your pull request and other information

AppType has members literally named dict, exec, help, max, set,
sum (IANA service names), which shadow builtins in bare :type: lookups.
:no-index: on its autoclass (reg.rst:76) fixes that, but also drops
AppType's own py-domain target — breaking every :class: link to it: 4
hand-written refs plus ~31 generated from type annotations in
pcapkit/protocols/schema/transport/*.py and transport/transport.py.

Added an invisible .. py:class:: AppType stub with :no-typesetting:
(reg.rst:73) immediately before the no-indexed autoclass. It registers
only the class's own target; docutils merges that anchor onto the
autoclass's signature block, so there's no visible duplicate header.
Restored the three hand-converted plain literals back to :class: links;
vendor/reg.rst:63's existing ref needed no edit, it resolves on its own.

Result: all ~35 :class: references to AppType are working links
again, including the annotation-generated ones. Its 8,182 members stay
unindexed (still visible as content) — no member is referenced anywhere.

Fresh -E build: 49 warnings before/after, byte-identical. Bare dict in
:type: fields still resolves to docs.python.org, not AppType.dict.
objects.inv: +1 py:class entry for AppType, 0 new py:attribute
entries for its members.

make test unticked: no test covers Sphinx xref resolution.
tests/project/test_documentation_claims.py states that's deliberate and
the measured counts belong in the PR instead — given above.

Changelog unticked: N/A — changelog centralised in #657.

Fixes #717.

@JarryShaw JarryShaw added bug docs Pull requests that change documentation only (docs: subject prefix) and removed bug labels Sep 23, 2026
@JarryShaw
JarryShaw force-pushed the fix/717-dict-rst-type-xref branch from 4bc9baf to e7652a1 Compare September 23, 2026 23:41
@JarryShaw JarryShaw changed the title fix(docs): qualify bare dict in four :type: fields fix(docs): stop AppType shadowing six builtins in cross-references Sep 23, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Superseded the `typing.Dict` approach with whole-class `:no-index:` on `AppType` — fixes all 6 builtin collisions (`dict, exec, help, max, set, sum`) instead of 1, and needs no change to the four `:type:` fields.

New head: `e7652a1c5978476267bbe3e05bab2b0d21c187b4`

  • `id="...AppType."` anchors in `const/reg.html`: 6 before → 0 after
  • Build warnings: 49 before → 49 after (unchanged)

Cost: 3 existing `:class:` refs to `AppType` itself (`pep.rst`, `protocols/application/index.rst`, `reg.rst`'s own table) can no longer resolve, converted to plain literals.

@JarryShaw

Copy link
Copy Markdown
Owner Author

✅ GOOD TO MERGE @ e7652a1c5 — full -E builds before/after: bare dict in every :type: field now links to Python's dict on docs.python.org instead of AppType.dict, 49 warnings both sides and byte-identical warning lines; one judgement call for you: ~31 more AppType links beyond the three the body lists (annotation-generated pages + vendor/reg.rst:63) silently unlink — the #module-pcapkit.const.reg.apptype anchor survives if you want :mod: links back.

@JarryShaw

Copy link
Copy Markdown
Owner Author

✅ GOOD TO MERGE @ e7652a1c5 — full -E builds before/after: bare dict in every :type: field now links to Python's dict on docs.python.org instead of AppType.dict, 49 warnings both sides and byte-identical warning lines; one judgement call for you: ~31 more AppType links beyond the three the body lists (annotation-generated pages + vendor/reg.rst:63) silently unlink — the #module-pcapkit.const.reg.apptype anchor survives if you want :mod: links back.

Measured on the merge result (main daa953d1b + the 3 files; branch is 2 commits behind main, true diff vs merge-base is exactly the 3 files). Both builds sphinx -E, Sphinx 9.1.0.

measure before after
warnings 49 49 — warning lines diff empty
dict at the 4 :type: sites const/reg.html#…AppType.dict docs.python.org/3/builtins/stdtypes.html#dict (v3.14)
id="…apptype.AppType*" anchors on reg.html 8,188 0 (module anchor survives; content still renders, 8,763 <dt>s)
objects.inv py entries 17,121 8,933
project suffix matches for bare dict/exec/help/set/sum 1 each (AppType member) 0 each
  • The bug was wider than docs: bare 'dict' in :type: fields resolves to AppType.dict, an IANA service enum member, not the builtin #717's four sites: 23 AppType.dict links across 12 pages (extraction, protocols/index, esp, pcapng, infoclass, field, …), 1 AppType.set (traceflow/tcp.html), 3 AppType.http linked out of URL text (const/sctp.html). All gone after; qualification could never have caught these — the :no-index: decision is verified right.
  • Links lost beyond the three converted refs, all rendering as unlinked code text with no warning (build is not nitpicky): docs/source/pcapkit/vendor/reg.rst:63 (:class: ref to const AppType, untouched) and ~31 annotation-generated links on udp/tcp/sctp/transport/registry pages. Judgement call, not a blocker: :mod:pcapkit.const.reg.apptype`` still resolves if you want a clickable path back.
  • New micro-regression: _modules/pcapkit/const/reg/apptype.html keeps 2 viewcode back-links to now-removed anchors (#…AppType, #…AppType._missing_) — they land at the top of reg.html.
  • Nothing else needs the same treatment: AppType is the only enumeration with builtin-named members in the whole 17k-entry inventory. Bare max stays ambiguous among 5 non-AppType .max attributes — pre-existing, and no bare max ref exists.
  • PR-body claims checked true: sphinx/directives/__init__.py:275-278 skips add_target_and_index under :no-index:; test_documentation_claims.py does say xref resolution is deliberately untested with counts recorded in the PR.

✅ GOOD TO MERGE @ e7652a1c5 — full -E builds before/after: bare dict in every :type: field now links to Python's dict on docs.python.org instead of AppType.dict, 49 warnings both sides and byte-identical warning lines; one judgement call for you: ~31 more AppType links beyond the three the body lists (annotation-generated pages + vendor/reg.rst:63) silently unlink — the #module-pcapkit.const.reg.apptype anchor survives if you want :mod: links back.

:no-index: on the AppType autoclass (reg.rst:76) fixed the builtin
collisions but also dropped AppType's own py-domain target, breaking
every :class: link to it -- the 4 hand-written refs plus ~31 more
generated from type annotations in pcapkit/protocols/schema/transport
and pcapkit/protocols/transport/transport.py.

Add an invisible `.. py:class:: AppType` stub with :no-typesetting:
right before the no-indexed autoclass (reg.rst:73). It registers just
the class's own cross-reference target; docutils merges that anchor
onto the autoclass's own signature block, so there's no visible
duplicate "class AppType" header. Members stay unindexed, still
visible as content.

Restored the three hand-converted plain literals (reg.rst's list-table
row, application/index.rst, pep.rst) back to :class: links.
vendor/reg.rst:63's existing :class: ref needed no edit -- it resolves
again automatically once AppType has a target.

Fresh -E build: 49 warnings before and after, byte-identical. Bare
dict in :type: fields still resolves to docs.python.org, confirming
the original fix isn't regressed. objects.inv: +1 py:class entry for
AppType, 0 new py:attribute entries for its members.

Fixes #717.
@JarryShaw
JarryShaw force-pushed the fix/717-dict-rst-type-xref branch from e7652a1 to 9d1fbd7 Compare September 24, 2026 02:52
@JarryShaw

Copy link
Copy Markdown
Owner Author

Status: candidate for closing, pending the maintainer's final call#732's redesign may subsume this.

Measured, since my earlier assessment that it would not: the per-transport split changes four of the six collisions, because Sphinx resolves silently only when exactly one target matches, and duplicating a member into both tcp and udp makes it ambiguous.

name port proto after #732
dict 2628 tcp|udp 2 targets → Sphinx warns
max 6074 tcp|udp 2 targets → Sphinx warns
set 257 tcp|udp 2 targets → Sphinx warns
sum 6551 tcp|udp 2 targets → Sphinx warns
help −1 undefined gone — -1 rows become docstring prose
exec 512 tcp 1 target → still silent

So #732 takes six collisions to one. Two caveats against closing:

  • exec survives. TCP-only, single target, so a bare `exec` in a :type: field would still resolve to the IANA service. This PR is the only thing that fixes it.
  • The four "fixed" ones become warnings, not correct links. A bare `dict` would stop pointing at an IANA service without pointing at Python's dict either — "more than one target found", rendered unlinked. Honest rather than wrong, but new noise in a build that has 49 warnings and no nitpicky setting.

This PR is now 9 added lines in one file (docs/source/pcapkit/const/reg.rst) and all ~35 AppType references resolve, including the 31 generated from annotations.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Closing unmerged, on the maintainer's decision: "i prefer we close it. no need to update the doc which is already determined to be updated/rewrote entirely."

#732 rewrites docs/source/pcapkit/const/reg.rst wholesale — one autoclass per transport registry replacing the single 8,182-member block this PR was editing — so the 9 lines here would be discarded rather than carried forward.

Issue #717 stays open. This PR carried Fixes #717., and closing unmerged does not close it, deliberately: the defect is still live and #732 must answer it.

What #732 does and does not fix, measured, so the redesign inherits the requirement rather than the assumption:

collision port proto after #732's split
dict 2628 tcp|udp 2 targets → Sphinx warns, renders unlinked
max 6074 tcp|udp 2 targets → warns
set 257 tcp|udp 2 targets → warns
sum 6551 tcp|udp 2 targets → warns
help −1 undefined gone — unassigned rows become docstring prose
exec 512 tcp 1 target → still resolves silently to the IANA service

Sphinx resolves silently only when exactly one target matches, so duplicating a member across tcp and udp converts a silent mis-resolution into a visible warning. That takes six collisions to one — but exec is TCP-only and survives, and the four "fixed" ones render unlinked rather than pointing at Python's dict.

Work not lost, for whoever picks up #717 under #732: the mechanism that keeps a class linkable while its members carry no targets is :no-typesetting: on a hand-written .. py:class:: stub (sphinx/directives/__init__.py:59,299-313). :no-index: and :no-index-entry: both share one options object across autodoc's recursive member walk, so class-indexed/members-unindexed is impossible through a single autoclass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Pull requests that change documentation only (docs: subject prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: bare 'dict' in :type: fields resolves to AppType.dict, an IANA service enum member, not the builtin

1 participant