Support `:no-index-entry: in .. {js,py}:module::` (#13272)

This commit is contained in:
Adam Turner 2025-01-28 01:33:28 +00:00 committed by GitHub
parent 60f88cc16e
commit 7801540c08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 59 additions and 21 deletions

View File

@ -73,6 +73,9 @@ Features added
* #9732: Add the new ``ref.any`` warnings sub-type
to allow suppressing the ambiguous 'any' cross-reference warning.
Patch by Simão Afonso and Adam Turner.
* #13272: The Python and JavaScript module directives now support
the ``:no-index-entry:`` option.
Patch by Adam Turner.
Bugs fixed
----------

View File

@ -48,7 +48,7 @@ the content should be the description.
A domain will typically keep an internal index of all entities to aid
cross-referencing.
Typically it will also add entries in the shown general index.
Typically, it will also add entries in the shown general index.
If you want to suppress the addition of an entry in the shown index, you can
give the directive option flag ``:no-index-entry:``.
If you want to exclude the object description from the table of contents, you

View File

@ -155,8 +155,8 @@ class JSObject(ObjectDescription[tuple[str, str]]):
def add_target_and_index(
self, name_obj: tuple[str, str], sig: str, signode: desc_signature
) -> None:
mod_name = self.env.ref_context.get('js:module')
fullname = (mod_name + '.' if mod_name else '') + name_obj[0]
mod_name = self.env.ref_context.get('js:module', '')
fullname = (f'{mod_name}.' if mod_name else '') + name_obj[0]
node_id = make_id(self.env, self.state.document, '', fullname)
signode['ids'].append(node_id)
self.state.document.note_explicit_target(signode)
@ -165,11 +165,10 @@ class JSObject(ObjectDescription[tuple[str, str]]):
domain.note_object(fullname, self.objtype, node_id, location=signode)
if 'no-index-entry' not in self.options:
indextext = self.get_index_text(mod_name, name_obj) # type: ignore[arg-type]
if indextext:
if index_text := self.get_index_text(mod_name, name_obj):
self.indexnode['entries'].append((
'single',
indextext,
index_text,
node_id,
'',
None,
@ -333,6 +332,7 @@ class JSModule(SphinxDirective):
final_argument_whitespace = False
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,
'noindex': directives.flag,
@ -365,9 +365,12 @@ class JSModule(SphinxDirective):
)
# The node order is: index node first, then target node
indextext = _('%s (module)') % mod_name
inode = addnodes.index(entries=[('single', indextext, node_id, '', None)])
ret.append(inode)
if 'no-index-entry' not in self.options:
index_text = _('%s (module)') % mod_name
inode = addnodes.index(
entries=[('single', index_text, node_id, '', None)]
)
ret.append(inode)
target = nodes.target('', '', ids=[node_id], ismod=True)
self.state.document.note_explicit_target(target)
ret.append(target)

View File

@ -479,6 +479,7 @@ class PyModule(SphinxDirective):
'platform': lambda x: x,
'synopsis': lambda x: x,
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,
'noindex': directives.flag,
@ -520,10 +521,15 @@ class PyModule(SphinxDirective):
# the platform and synopsis aren't printed; in fact, they are only
# used in the modindex currently
indextext = f'module; {modname}'
inode = addnodes.index(entries=[('pair', indextext, node_id, '', None)])
# The node order is: index node first, then target node.
ret.extend((inode, target))
if 'no-index-entry' not in self.options:
index_text = f'module; {modname}'
inode = addnodes.index(
entries=[('pair', index_text, node_id, '', None)]
)
# The node order is: index node first, then target node.
ret.append(inode)
ret.append(target)
ret.extend(content_nodes)
return ret

View File

@ -409,8 +409,8 @@ class PyObject(ObjectDescription[tuple[str, str]]):
def add_target_and_index(
self, name_cls: tuple[str, str], sig: str, signode: desc_signature
) -> None:
modname = self.options.get('module', self.env.ref_context.get('py:module'))
fullname = (f'{modname}.' if modname else '') + name_cls[0]
mod_name = self.options.get('module', self.env.ref_context.get('py:module'))
fullname = (f'{mod_name}.' if mod_name else '') + name_cls[0]
node_id = make_id(self.env, self.state.document, '', fullname)
signode['ids'].append(node_id)
self.state.document.note_explicit_target(signode)
@ -425,11 +425,10 @@ class PyObject(ObjectDescription[tuple[str, str]]):
)
if 'no-index-entry' not in self.options:
indextext = self.get_index_text(modname, name_cls)
if indextext:
if index_text := self.get_index_text(mod_name, name_cls):
self.indexnode['entries'].append((
'single',
indextext,
index_text,
node_id,
'',
None,

View File

@ -57,11 +57,10 @@ class ReSTMarkup(ObjectDescription[str]):
domain.note_object(self.objtype, name, node_id, location=signode)
if 'no-index-entry' not in self.options:
indextext = self.get_index_text(self.objtype, name)
if indextext:
if index_text := self.get_index_text(self.objtype, name):
self.indexnode['entries'].append((
'single',
indextext,
index_text,
node_id,
'',
None,

View File

@ -326,6 +326,25 @@ def test_no_index_entry(app):
)
assert_node(doctree[2], addnodes.index, entries=[])
text = '.. js:class:: f\n.. js:class:: g\n :no-index-entry:\n'
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(
doctree[0],
addnodes.index,
entries=[('single', 'f() (class)', 'f', '', None)],
)
assert_node(doctree[2], addnodes.index, entries=[])
text = '.. js:module:: f\n.. js:module:: g\n :no-index-entry:\n'
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, nodes.target, nodes.target))
assert_node(
doctree[0],
addnodes.index,
entries=[('single', 'f (module)', 'module-f', '', None)],
)
@pytest.mark.sphinx('html', testroot='root')
def test_module_content_line_number(app):

View File

@ -836,6 +836,15 @@ def test_no_index_entry(app):
)
assert_node(doctree[2], addnodes.index, entries=[])
text = '.. py:module:: f\n.. py:module:: g\n :no-index-entry:\n'
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, nodes.target, nodes.target))
assert_node(
doctree[0],
addnodes.index,
entries=[('pair', 'module; f', 'module-f', '', None)],
)
@pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names')
def test_python_python_use_unqualified_type_names(app):