mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #9121: py domain: duplicated warning for canonical and alias
A duplicated warning is emitted when both canonical and its alias objects are defined on the same document. But it should not be emitted because they're the same object, not conflicted.
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -23,6 +23,8 @@ Features added
|
|||||||
* #9098: html: copy-range protection for doctests doesn't work in Safari
|
* #9098: html: copy-range protection for doctests doesn't work in Safari
|
||||||
* #9103: LaTeX: imgconverter: conversion runs even if not needed
|
* #9103: LaTeX: imgconverter: conversion runs even if not needed
|
||||||
* #8127: py domain: Ellipsis in info-field-list causes nit-picky warning
|
* #8127: py domain: Ellipsis in info-field-list causes nit-picky warning
|
||||||
|
* #9121: py domain: duplicated warning is emitted when both canonical and its
|
||||||
|
alias objects are defined on the document
|
||||||
* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.
|
* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class ObjectEntry(NamedTuple):
|
|||||||
docname: str
|
docname: str
|
||||||
node_id: str
|
node_id: str
|
||||||
objtype: str
|
objtype: str
|
||||||
canonical: bool
|
aliased: bool
|
||||||
|
|
||||||
|
|
||||||
class ModuleEntry(NamedTuple):
|
class ModuleEntry(NamedTuple):
|
||||||
@@ -505,7 +505,7 @@ class PyObject(ObjectDescription[Tuple[str, str]]):
|
|||||||
|
|
||||||
canonical_name = self.options.get('canonical')
|
canonical_name = self.options.get('canonical')
|
||||||
if canonical_name:
|
if canonical_name:
|
||||||
domain.note_object(canonical_name, self.objtype, node_id, canonical=True,
|
domain.note_object(canonical_name, self.objtype, node_id, aliased=True,
|
||||||
location=signode)
|
location=signode)
|
||||||
|
|
||||||
if 'noindexentry' not in self.options:
|
if 'noindexentry' not in self.options:
|
||||||
@@ -1138,17 +1138,25 @@ class PythonDomain(Domain):
|
|||||||
return self.data.setdefault('objects', {}) # fullname -> ObjectEntry
|
return self.data.setdefault('objects', {}) # fullname -> ObjectEntry
|
||||||
|
|
||||||
def note_object(self, name: str, objtype: str, node_id: str,
|
def note_object(self, name: str, objtype: str, node_id: str,
|
||||||
canonical: bool = False, location: Any = None) -> None:
|
aliased: bool = False, location: Any = None) -> None:
|
||||||
"""Note a python object for cross reference.
|
"""Note a python object for cross reference.
|
||||||
|
|
||||||
.. versionadded:: 2.1
|
.. versionadded:: 2.1
|
||||||
"""
|
"""
|
||||||
if name in self.objects:
|
if name in self.objects:
|
||||||
other = self.objects[name]
|
other = self.objects[name]
|
||||||
logger.warning(__('duplicate object description of %s, '
|
if other.aliased and aliased is False:
|
||||||
'other instance in %s, use :noindex: for one of them'),
|
# The original definition found. Override it!
|
||||||
name, other.docname, location=location)
|
pass
|
||||||
self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, canonical)
|
elif other.aliased is False and aliased:
|
||||||
|
# The original definition is already registered.
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# duplicated
|
||||||
|
logger.warning(__('duplicate object description of %s, '
|
||||||
|
'other instance in %s, use :noindex: for one of them'),
|
||||||
|
name, other.docname, location=location)
|
||||||
|
self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, aliased)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def modules(self) -> Dict[str, ModuleEntry]:
|
def modules(self) -> Dict[str, ModuleEntry]:
|
||||||
@@ -1326,8 +1334,8 @@ class PythonDomain(Domain):
|
|||||||
yield (modname, modname, 'module', mod.docname, mod.node_id, 0)
|
yield (modname, modname, 'module', mod.docname, mod.node_id, 0)
|
||||||
for refname, obj in self.objects.items():
|
for refname, obj in self.objects.items():
|
||||||
if obj.objtype != 'module': # modules are already handled
|
if obj.objtype != 'module': # modules are already handled
|
||||||
if obj.canonical:
|
if obj.aliased:
|
||||||
# canonical names are not full-text searchable.
|
# aliased names are not full-text searchable.
|
||||||
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, -1)
|
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, -1)
|
||||||
else:
|
else:
|
||||||
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)
|
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)
|
||||||
|
|||||||
@@ -870,6 +870,39 @@ def test_canonical(app):
|
|||||||
assert domain.objects['_io.StringIO'] == ('index', 'io.StringIO', 'class', True)
|
assert domain.objects['_io.StringIO'] == ('index', 'io.StringIO', 'class', True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_canonical_definition_overrides(app, warning):
|
||||||
|
text = (".. py:class:: io.StringIO\n"
|
||||||
|
" :canonical: _io.StringIO\n"
|
||||||
|
".. py:class:: _io.StringIO\n")
|
||||||
|
restructuredtext.parse(app, text)
|
||||||
|
assert warning.getvalue() == ""
|
||||||
|
|
||||||
|
domain = app.env.get_domain('py')
|
||||||
|
assert domain.objects['_io.StringIO'] == ('index', 'id0', 'class', False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_canonical_definition_skip(app, warning):
|
||||||
|
text = (".. py:class:: _io.StringIO\n"
|
||||||
|
".. py:class:: io.StringIO\n"
|
||||||
|
" :canonical: _io.StringIO\n")
|
||||||
|
|
||||||
|
restructuredtext.parse(app, text)
|
||||||
|
assert warning.getvalue() == ""
|
||||||
|
|
||||||
|
domain = app.env.get_domain('py')
|
||||||
|
assert domain.objects['_io.StringIO'] == ('index', 'io.StringIO', 'class', False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_canonical_duplicated(app, warning):
|
||||||
|
text = (".. py:class:: mypackage.StringIO\n"
|
||||||
|
" :canonical: _io.StringIO\n"
|
||||||
|
".. py:class:: io.StringIO\n"
|
||||||
|
" :canonical: _io.StringIO\n")
|
||||||
|
|
||||||
|
restructuredtext.parse(app, text)
|
||||||
|
assert warning.getvalue() != ""
|
||||||
|
|
||||||
|
|
||||||
def test_info_field_list(app):
|
def test_info_field_list(app):
|
||||||
text = (".. py:module:: example\n"
|
text = (".. py:module:: example\n"
|
||||||
".. py:class:: Class\n"
|
".. py:class:: Class\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user