I'm running into some trouble trying to link to the PyQt5 docs using intersphinx
.
Trying to cross reference any of the QtCore
classes (such as QThread
) does not work as I'd expect. I have parsed the objects.inv
available here using python -m sphinx.ext.intersphinx objects.inv
, which results in an output shown in thisgist .
Unfortunately, under the python namespace there are no classes and only a few functions. Everything PyQt5
-related is in the sip:class
namespace. Trying to reference this in documentation using the standard :py:class:
syntax does not link to anything (since sphinx doesn't see that reference connected to anything), and using :sip:class:
causes a warning of Unknown interpreted text role "sip:class"
, which makes sense because that is not a known reference code.
So, how do we access the documentation of PyQt through intersphinx (if we can at all)?
EDIT: I create python package with this solution: https://pypi.org/project/sphinx-qt-documentation/
ORIGINAL ANSWER:
I use another approach to this problem. I create custom sphinx plugin to translate on fly inventory file to use sip
domain. It allows to chose which documentation should be pointed (pleas see docstring on top). It works on my project, but I'm not sure if it support all cases.
This extension need sphinx.ext.intersphinx
extension to be configured in sphinx extension and PyQt
configure in mapping
intersphinx_mapping = {...,
"PyQt": ("https://www.riverbankcomputing.com/static/Docs/PyQt5", None)}
"""
This module contains sphinx extension supporting for build PartSeg documentation.
this extensio provides one configuration option:
`qt_documentation` with possibe values:
* PyQt - linking to PyQt documentation on https://www.riverbankcomputing.com/static/Docs/PyQt5/api/ (incomplete)
* Qt - linking to Qt documentation on "https://doc.qt.io/qt-5/" (default)
* PySide - linking to PySide documentation on "https://doc.qt.io/qtforpython/PySide2/"
"""
import re
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
from docutils.nodes import Element, TextElement
from docutils import nodes
from typing import List, Optional, Dict, Any
from sphinx.locale import _
from sphinx.ext.intersphinx import InventoryAdapter
try:
from qtpy import QT_VERSION
except ImportError:
QT_VERSION = None
# TODO add response to
# https://stackoverflow.com/questions/47102004/how-to-properly-link-to-pyqt5-documentation-using-intersphinx
signal_slot_uri = {
"Qt": "https://doc.qt.io/qt-5/signalsandslots.html",
"PySide": "https://doc.qt.io/qtforpython/overviews/signalsandslots.html",
"PyQt": "https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html"
}
signal_name = {
"Qt": "Signal",
"PySide": "Signal",
"PyQt": "pyqtSignal"
}
slot_name = {
"Qt": "Slot",
"PySide": "Slot",
"PyQt": "pyqtSlot"
}
signal_pattern = re.compile(r'((\w+\d?\.QtCore\.)|(QtCore\.)|(\.)())?(pyqt)?Signal')
slot_pattern = re.compile(r'((\w+\d?\.QtCore\.)|(QtCore\.)|(\.)())?(pyqt)?Slot')
def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: TextElement
) -> Optional[nodes.reference]:
"""Linking to Qt documentation."""
target: str = node['reftarget']
inventories = InventoryAdapter(env)
objtypes = None # type: Optional[List[str]]
if node['reftype'] == 'any':
# we search anything!
objtypes = ['%s:%s' % (domain.name, objtype)
for domain in env.domains.values()
for objtype in domain.object_types]
domain = None
else:
domain = node.get('refdomain')
if not domain:
# only objects in domains are in the inventory
return None
objtypes = env.get_domain(domain).objtypes_for_role(node['reftype'])
if not objtypes:
return None
objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
if target.startswith("PySide2"):
head, tail = target.split(".", 1)
target = "PyQt5." + tail
obj_type_name = "sip:{}".format(node.get("reftype"))
if obj_type_name not in inventories.named_inventory["PyQt"]:
return None
target_list = [target, "PyQt5." + target]
target_list += [name + "." + target for name in inventories.named_inventory["PyQt"]["sip:module"].keys()]
if signal_pattern.match(target):
uri = signal_slot_uri[app.config.qt_documentation]
dispname = signal_name[app.config.qt_documentation]
version = QT_VERSION
elif slot_pattern.match(target):
uri = signal_slot_uri[app.config.qt_documentation]
dispname = slot_name[app.config.qt_documentation]
version = QT_VERSION
else:
for target_name in target_list:
if target_name in inventories.main_inventory[obj_type_name]:
proj, version, uri, dispname = inventories.named_inventory["PyQt"][obj_type_name][target_name]
print(node) # print nodes with unresolved references
break
else:
return None
if app.config.qt_documentation == "Qt":
html_name = uri.split("/")[-1]
uri = "https://doc.qt.io/qt-5/" + html_name
elif app.config.qt_documentation == "PySide":
html_name = "/".join(target.split(".")[1:]) + ".html"
uri = "https://doc.qt.io/qtforpython/PySide2/" + html_name
# remove this line if you would like straight to pyqt documentation
if version:
reftitle = _('(in %s v%s)') % (app.config.qt_documentation, version)
else:
reftitle = _('(in %s)') % (app.config.qt_documentation,)
newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle)
if node.get('refexplicit'):
# use whatever title was given
newnode.append(contnode)
else:
# else use the given display name (used for :ref:)
newnode.append(contnode.__class__(dispname, dispname))
return newnode
def setup(app: Sphinx) -> Dict[str, Any]:
app.connect('missing-reference', missing_reference)
app.add_config_value('qt_documentation', "Qt", True)
return {
'version': "0.9",
'env_version': 1,
'parallel_read_safe': True
}
In order to get intersphinx
mapping to work for my project that uses PyQt5 I did the following:
:sip:
domain to be :py:
QWidget
in my documentation they are directed to Qt-QWidget:class:`QWidget`
, :class:`QtWidgets.QWidget`
and :class:`PyQt5.QtWidgets.QWidget`
are all linked to Qt-QWidget If you would like to use my modified objects.inv
file in your own project you can download it, save it to the same directory as your conf.py
file and then edit your intersphinx_mapping
dictionary in your conf.py
to be
intersphinx_mapping = {
# 'PyQt5': ('http://pyqt.sourceforge.net/Docs/PyQt5/', None),
'PyQt5': ('', 'pyqt5-modified-objects.inv'),
}
If my 'pyqt5-modified-objects.inv'
file does not meet the requirements for your project (for example, I did not add aliases for all Qt modules, only QtWidgets
, QtCore
and QtGui
) then you can modify the source code that automatically performs steps 1 - 4 above.
The source code can also be used to create a modified objects.inv
file for PyQt4; however, the original objects.inv
file for PyQt4 does not contain a complete listing of all Qt modules and classes and therefore using intersphinx
mapping with PyQt4 isn't very useful.
Note: The SourceForge team is currently solving some issues and so executing the source code will raise a ConnectionError
until their issues are resolved.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.