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 * #9732: Add the new ``ref.any`` warnings sub-type
to allow suppressing the ambiguous 'any' cross-reference warning. to allow suppressing the ambiguous 'any' cross-reference warning.
Patch by Simão Afonso and Adam Turner. 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 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 A domain will typically keep an internal index of all entities to aid
cross-referencing. 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 If you want to suppress the addition of an entry in the shown index, you can
give the directive option flag ``:no-index-entry:``. give the directive option flag ``:no-index-entry:``.
If you want to exclude the object description from the table of contents, you 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( def add_target_and_index(
self, name_obj: tuple[str, str], sig: str, signode: desc_signature self, name_obj: tuple[str, str], sig: str, signode: desc_signature
) -> None: ) -> None:
mod_name = self.env.ref_context.get('js:module') mod_name = self.env.ref_context.get('js:module', '')
fullname = (mod_name + '.' if mod_name else '') + name_obj[0] fullname = (f'{mod_name}.' if mod_name else '') + name_obj[0]
node_id = make_id(self.env, self.state.document, '', fullname) node_id = make_id(self.env, self.state.document, '', fullname)
signode['ids'].append(node_id) signode['ids'].append(node_id)
self.state.document.note_explicit_target(signode) 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) domain.note_object(fullname, self.objtype, node_id, location=signode)
if 'no-index-entry' not in self.options: if 'no-index-entry' not in self.options:
indextext = self.get_index_text(mod_name, name_obj) # type: ignore[arg-type] if index_text := self.get_index_text(mod_name, name_obj):
if indextext:
self.indexnode['entries'].append(( self.indexnode['entries'].append((
'single', 'single',
indextext, index_text,
node_id, node_id,
'', '',
None, None,
@ -333,6 +332,7 @@ class JSModule(SphinxDirective):
final_argument_whitespace = False final_argument_whitespace = False
option_spec: ClassVar[OptionSpec] = { option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag, 'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag, 'no-contents-entry': directives.flag,
'no-typesetting': directives.flag, 'no-typesetting': directives.flag,
'noindex': directives.flag, 'noindex': directives.flag,
@ -365,8 +365,11 @@ class JSModule(SphinxDirective):
) )
# The node order is: index node first, then target node # The node order is: index node first, then target node
indextext = _('%s (module)') % mod_name if 'no-index-entry' not in self.options:
inode = addnodes.index(entries=[('single', indextext, node_id, '', None)]) index_text = _('%s (module)') % mod_name
inode = addnodes.index(
entries=[('single', index_text, node_id, '', None)]
)
ret.append(inode) ret.append(inode)
target = nodes.target('', '', ids=[node_id], ismod=True) target = nodes.target('', '', ids=[node_id], ismod=True)
self.state.document.note_explicit_target(target) self.state.document.note_explicit_target(target)

View File

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

View File

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

View File

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

View File

@ -326,6 +326,25 @@ def test_no_index_entry(app):
) )
assert_node(doctree[2], addnodes.index, entries=[]) 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') @pytest.mark.sphinx('html', testroot='root')
def test_module_content_line_number(app): 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=[]) 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') @pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names')
def test_python_python_use_unqualified_type_names(app): def test_python_python_use_unqualified_type_names(app):