fix(python-docs): cross-link package overview re-export stubs#39
fix(python-docs): cross-link package overview re-export stubs#39WomB0ComB0 merged 1 commit intomainfrom
Conversation
pydoc-markdown emits an empty `## ClassName` heading on each `<package>/overview.md` for every name re-exported from the package's `__init__.py`. The class/function bodies live on submodule pages (e.g. `models.md`, `tools.md`), so the overview's right-side TOC entries previously led to dead-end in-page anchors with no content. Replace the empty stub block with a clean `## API` section listing each symbol as a link to where it's actually defined. Symbols are located by scanning non-overview pages for canonical definition shapes that pydoc-markdown uses: `## ClassName Objects` -> class definition `#### function_name` -> function definition Heuristic h2-without-"Objects" and h3 are skipped because pydoc-markdown reuses them for re-export stubs and class-internal sub-sections respectively. Adds the same logic as a workflow step in the source-repo template so future regenerations keep the cross-links fresh.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces an automation step to replace empty re-export stubs in Python API documentation with a cross-linked 'API' section. Feedback indicates that the current implementation might accidentally delete trailing content in overview.md files. Suggestions were also made to ensure the symbol scanning logic ignores code blocks and to sort file results for deterministic behavior.
| stubs = list(stub_re.finditer(text)) | ||
| if not stubs: | ||
| continue | ||
| pre = text[: stubs[0].start()].rstrip() + "\n\n" |
There was a problem hiding this comment.
This logic assumes that all stubs are located at the end of the overview.md file and that no important content exists after the first detected stub. By using text[: stubs[0].start()], any content following the first stub (such as a footer, manual notes, or even non-empty headings that didn't match the stub_re) will be permanently deleted during the rewrite. It would be safer to replace only the specific ranges occupied by the stubs or to ensure that trailing content is preserved.
| heading_re = re.compile( | ||
| r'<a id="([^"]+)"></a>\n+(#{2,6})\s+([^\n]+?)\n' | ||
| ) |
There was a problem hiding this comment.
The regex-based scanning for headings does not account for CommonMark inline code spans or blocks. If a documentation page contains an example code block that includes a string matching the anchor and heading pattern, it will be incorrectly indexed in the symbol_map. Per the general rules, parsing logic should respect code boundaries to avoid modifying or indexing content inside snippets.
References
- When processing Markdown/MDX files to escape curly braces for JSX compatibility, ensure the logic ignores content within inline code spans (backticks) to prevent breaking code snippets.
| ) | ||
|
|
||
| symbol_map: dict[tuple[str, str], tuple[str, str]] = {} | ||
| for md in root.rglob("*.md"): |
There was a problem hiding this comment.
The use of rglob without sorting results in non-deterministic behavior when building the symbol_map. If multiple files contain definitions for the same symbol name (e.g., in different submodules), the link target in the overview will depend on the filesystem iteration order. Sorting the file list ensures consistent results across different environments.
for md in sorted(root.rglob("*.md")):Sync from resq-software/docs#39. Adds a post-process step that rewrites each <package>/overview.md so the empty class/function stubs (re-exports from __init__.py) become a clean ## API list with links to the submodule pages where each symbol is actually defined.
Summary
The package overview pages (`resq-dsa/overview.md`, `resq-mcp/overview.md`) had a list of empty class/function headings — `## Coordinates`, `## DetectedObject`, `## Settings`, etc. — with no content beneath them. Right-side TOC entries clicked to dead-end in-page anchors because the actual class bodies live on submodule pages (`models.md`, `core/config.md`, `tools.md`, etc.) where they were emitted from the source modules, not from the package's `init.py` re-exports.
Fix
Replace the empty stub block with a clean `## API` section listing each symbol as a link to where it's actually defined.
Symbol locations are computed by scanning every non-overview page for canonical pydoc-markdown definition shapes:
Stubs (h2 without "Objects") and class-internal sub-sections (h3) are deliberately skipped — those aren't standalone symbols.
Result
`resq-mcp/overview.md` now ends with a 30-entry `## API` block where every symbol points to its definition page and slug:
The same logic is added as a step in `automation/source-repo-templates/api-docs.python.yml` so future regenerations stay correct.
Test plan