Skip to content

SG-45110 Skip Qt binding members in autodoc to fix PySide6 doc builds - #84

Open
julien-lang wants to merge 13 commits into
masterfrom
ticket/SG-45110-fix-pyside6-duplicate-object-docs
Open

julien-lang wants to merge 13 commits into
masterfrom
ticket/SG-45110-fix-pyside6-duplicate-object-docs

Conversation

@julien-lang

@julien-lang julien-lang commented Sep 9, 2026

Copy link
Copy Markdown
Member

Problem

Building documentation for tk-framework-qtwidgets with PySide6 fails under -W with sphinx.errors.SphinxWarning: duplicate object description of PySide6.QtGui.QPaintDevice.PaintDeviceMetric, other instance in activity_stream, use :noindex: for one of them.
tk-framework-qtwidgets documents real QWidget subclasses (ActivityStreamWidget, ReplyListWidget, etc.) using :inherited-members:. With PySide2, nested Qt enums (e.g. QPaintDevice.PaintDeviceMetric) aren't real Python classes, so autodoc never walked into them. With PySide6 they are real classes, so :inherited-members: pulls them in as documented members of every widget that inherits them, and Sphinx registers the same Qt-native class multiple times across different modules, which it flags as a duplicate object description and aborts the build.
tk-core and other bundles that use :inherited-members: document plain Python classes (Engine, Application, Sgtk, etc.), never Qt classes, so they never hit this. Any tk-* bundle documenting real Qt widget subclasses would hit the same issue once built with PySide6.

Fix

Added an autodoc-skip-member hook in the shared conf.py (used by all tk-* doc builds) that skips any member whose __module__ belongs to the Qt binding itself (PySide2/PySide6/PyQt4/PyQt5), since those are already covered via intersphinx_mapping.
No documented content is lost: PySide2 docs never generated standalone pages for these nested enums either, they only ever appeared as inline type references in method signatures.
Also stream Toolkit's debug logs to stdout during the doc build, since they were otherwise silently swallowed and made it hard to diagnose QtImporter failures while investigating this issue. Also fixed an UnboundLocalError caused by a redundant nested import sys shadowing the module-level import.

Testing

Verified locally with a PySide6 venv (tk-framework-qtwidgets/pyenv-build-doc) using tk-docs-preview --build-only.
Before the fix: build fails with 25 duplicate object description warnings across 9 Qt enum/flag classes.
After the fix: tk-framework-qtwidgets and tk-core docs both build successfully under -W, with no regression in previously-documented content (spot-checked ActivityStreamWidget.acceptDrops, allow_screenshots, attachments_filter, etc.).
Also validated end-to-end on Rundeck against tk-internal's release pipeline.
Related: SG-45110, SG-44795

tk-framework-qtwidgets documents QWidget subclasses with :inherited-members:.
With PySide2, nested Qt enums aren't real Python classes so autodoc never
walked into them. With PySide6 they are real classes, so :inherited-members:
pulls them in per widget, and Sphinx flags the repeated Qt-native class as a
duplicate object description, aborting the build under -W.

Skip autodoc members whose __module__ belongs to the Qt binding itself
(PySide2/PySide6/PyQt4/PyQt5), since those are already covered via
intersphinx_mapping. No documented content is lost: PySide2 never generated
standalone pages for these nested enums either, only inline signature
references.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Limit filtering to mapped bindings or add PyQt inventories to avoid losing undocumented replacement content.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates shared Sphinx autodoc configuration to prevent duplicate Qt-binding documentation during PySide6 builds.

Changes:

  • Adds and registers a hook to skip Qt-binding members.
  • Filters inherited Qt members from autodoc output.
File summaries
File Summary Review finding
tk_toolchain/cmd_line_tools/tk_docs_generation/sphinx_data/conf.py Filters Qt-binding members during documentation generation. Moderate: PyQt4/PyQt5 members are skipped without corresponding intersphinx inventories; 2 votes.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tk_toolchain/cmd_line_tools/tk_docs_generation/sphinx_data/conf.py Outdated
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 49.72%. Comparing base (538f78e) to head (a57e412).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #84      +/-   ##
==========================================
+ Coverage   48.95%   49.72%   +0.76%     
==========================================
  Files          19       19              
  Lines         721      732      +11     
==========================================
+ Hits          353      364      +11     
  Misses        368      368              
Flag Coverage Δ
Linux 49.31% <100.00%> (+0.77%) ⬆️
Python-3.10 49.31% <100.00%> (+0.77%) ⬆️
Python-3.11 49.72% <100.00%> (+0.76%) ⬆️
Python-3.13 49.72% <100.00%> (+0.76%) ⬆️
Python-3.9 49.31% <100.00%> (+0.77%) ⬆️
Windows 49.31% <100.00%> (+0.77%) ⬆️
macOS 49.45% <100.00%> (+0.77%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Overriding __eq__/__ne__ on _QtStubMeta broke class identity comparisons
for real bundle classes subclassing the stub (metaclasses propagate to
subclasses), making Sphinx's inherited-member filter treat every
subclass as equal to its base, which duplicated base-class members
(e.g. ViewItemDelegate.Padding) across subclass docs.
Useful for diagnosing QtImporter failures (and other tank-level issues)
directly from the Rundeck build log instead of hitting confusing
errors deep inside autodoc with no visibility into the real cause.
@julien-lang
julien-lang requested a lite review from Copilot September 15, 2026 18:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Qt-member filter must cover all supported binding prefixes, not only PySide6.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread tk_toolchain/cmd_line_tools/tk_docs_generation/sphinx_data/conf.py
@julien-lang
julien-lang marked this pull request as ready for review September 15, 2026 19:13
@julien-lang
julien-lang requested review from a team, stevelittlefish and yungsiow September 15, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants