mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #7199: py domain: Add a new confval: python_use_unqualified_type_names
Add a new config variable: python_use_unqualified_type_names. If enabled, it goes to suppress the module name of the python reference if it can be resolved.
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -60,6 +60,8 @@ Features added
|
||||
* #8924: autodoc: Support ``bound`` argument for TypeVar
|
||||
* #4826: py domain: Add ``:canonical:`` option to python directives to describe
|
||||
the location where the object is defined
|
||||
* #7199: py domain: Add :confval:`python_use_unqualified_type_names` to suppress
|
||||
the module name of the python reference if it can be resolved (experimental)
|
||||
* #7784: i18n: The alt text for image is translated by default (without
|
||||
:confval:`gettext_additional_targets` setting)
|
||||
* #2018: html: :confval:`html_favicon` and :confval:`html_logo` now accept URL
|
||||
|
||||
@@ -2714,6 +2714,17 @@ Options for the C++ domain
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
Options for the Python domain
|
||||
-----------------------------
|
||||
|
||||
.. confval:: python_use_unqualified_type_names
|
||||
|
||||
If true, suppress the module name of the python reference if it can be
|
||||
resolved. The default is ``False``.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
|
||||
.. note:: This configuration is still in experimental
|
||||
|
||||
Example of configuration file
|
||||
=============================
|
||||
|
||||
@@ -22,7 +22,7 @@ from docutils.nodes import Element, Node
|
||||
from docutils.parsers.rst import directives
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.addnodes import desc_signature, pending_xref
|
||||
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
@@ -37,7 +37,7 @@ from sphinx.util import logging
|
||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.inspect import signature_from_str
|
||||
from sphinx.util.nodes import make_id, make_refnode
|
||||
from sphinx.util.nodes import find_pending_xref_condition, make_id, make_refnode
|
||||
from sphinx.util.typing import TextlikeNode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -92,7 +92,17 @@ def type_to_xref(text: str, env: BuildEnvironment = None) -> addnodes.pending_xr
|
||||
else:
|
||||
kwargs = {}
|
||||
|
||||
return pending_xref('', nodes.Text(text),
|
||||
if env.config.python_use_unqualified_type_names:
|
||||
# Note: It would be better to use qualname to describe the object to support support
|
||||
# nested classes. But python domain can't access the real python object because this
|
||||
# module should work not-dynamically.
|
||||
shortname = text.split('.')[-1]
|
||||
contnodes = [pending_xref_condition('', shortname, condition='resolved'),
|
||||
pending_xref_condition('', text, condition='*')] # type: List[Node]
|
||||
else:
|
||||
contnodes = [nodes.Text(text)]
|
||||
|
||||
return pending_xref('', *contnodes,
|
||||
refdomain='py', reftype=reftype, reftarget=text, **kwargs)
|
||||
|
||||
|
||||
@@ -1209,7 +1219,15 @@ class PythonDomain(Domain):
|
||||
if obj[2] == 'module':
|
||||
return self._make_module_refnode(builder, fromdocname, name, contnode)
|
||||
else:
|
||||
return make_refnode(builder, fromdocname, obj[0], obj[1], contnode, name)
|
||||
# determine the content of the reference by conditions
|
||||
content = find_pending_xref_condition(node, 'resolved')
|
||||
if content:
|
||||
children = content.children
|
||||
else:
|
||||
# if not found, use contnode
|
||||
children = [contnode]
|
||||
|
||||
return make_refnode(builder, fromdocname, obj[0], obj[1], children, name)
|
||||
|
||||
def resolve_any_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
|
||||
target: str, node: pending_xref, contnode: Element
|
||||
@@ -1226,9 +1244,17 @@ class PythonDomain(Domain):
|
||||
self._make_module_refnode(builder, fromdocname,
|
||||
name, contnode)))
|
||||
else:
|
||||
# determine the content of the reference by conditions
|
||||
content = find_pending_xref_condition(node, 'resolved')
|
||||
if content:
|
||||
children = content.children
|
||||
else:
|
||||
# if not found, use contnode
|
||||
children = [contnode]
|
||||
|
||||
results.append(('py:' + self.role_for_objtype(obj[2]),
|
||||
make_refnode(builder, fromdocname, obj[0], obj[1],
|
||||
contnode, name)))
|
||||
children, name)))
|
||||
return results
|
||||
|
||||
def _make_module_refnode(self, builder: Builder, fromdocname: str, name: str,
|
||||
@@ -1295,6 +1321,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.setup_extension('sphinx.directives')
|
||||
|
||||
app.add_domain(PythonDomain)
|
||||
app.add_config_value('python_use_unqualified_type_names', False, 'env')
|
||||
app.connect('object-description-transform', filter_meta_fields)
|
||||
app.connect('missing-reference', builtin_resolver, priority=900)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import re
|
||||
import unicodedata
|
||||
from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Set, Tuple, Type, cast
|
||||
from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Set, Tuple, Type, Union, cast
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element, Node
|
||||
@@ -542,7 +542,7 @@ def find_pending_xref_condition(node: addnodes.pending_xref, condition: str) ->
|
||||
|
||||
|
||||
def make_refnode(builder: "Builder", fromdocname: str, todocname: str, targetid: str,
|
||||
child: Node, title: str = None) -> nodes.reference:
|
||||
child: Union[Node, List[Node]], title: str = None) -> nodes.reference:
|
||||
"""Shortcut to create a reference node."""
|
||||
node = nodes.reference('', '', internal=True)
|
||||
if fromdocname == todocname and targetid:
|
||||
@@ -555,7 +555,7 @@ def make_refnode(builder: "Builder", fromdocname: str, todocname: str, targetid:
|
||||
node['refuri'] = builder.get_relative_uri(fromdocname, todocname)
|
||||
if title:
|
||||
node['reftitle'] = title
|
||||
node.append(child)
|
||||
node += child
|
||||
return node
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
python_use_unqualified_type_names = True
|
||||
@@ -0,0 +1,8 @@
|
||||
domain-py-smart_reference
|
||||
=========================
|
||||
|
||||
.. py:class:: Name
|
||||
:module: foo
|
||||
|
||||
|
||||
.. py:function:: hello(name: foo.Name, age: foo.Age)
|
||||
@@ -999,6 +999,25 @@ def test_noindexentry(app):
|
||||
assert_node(doctree[2], addnodes.index, entries=[])
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names')
|
||||
def test_python_python_use_unqualified_type_names(app, status, warning):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert ('<span class="n"><a class="reference internal" href="#foo.Name" title="foo.Name">'
|
||||
'<span class="pre">Name</span></a></span>' in content)
|
||||
assert '<span class="n"><span class="pre">foo.Age</span></span>' in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names',
|
||||
confoverrides={'python_use_unqualified_type_names': False})
|
||||
def test_python_python_use_unqualified_type_names_disabled(app, status, warning):
|
||||
app.build()
|
||||
content = (app.outdir / 'index.html').read_text()
|
||||
assert ('<span class="n"><a class="reference internal" href="#foo.Name" title="foo.Name">'
|
||||
'<span class="pre">foo.Name</span></a></span>' in content)
|
||||
assert '<span class="n"><span class="pre">foo.Age</span></span>' in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='domain-py-xref-warning')
|
||||
def test_warn_missing_reference(app, status, warning):
|
||||
app.build()
|
||||
|
||||
Reference in New Issue
Block a user