Skip to content

Commit 7801540

Browse files
authored
Support :no-index-entry: in .. {js,py}:module:: (#13272)
1 parent 60f88cc commit 7801540

File tree

8 files changed

+59
-21
lines changed

8 files changed

+59
-21
lines changed

CHANGES.rst

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ Features added
7373
* #9732: Add the new ``ref.any`` warnings sub-type
7474
to allow suppressing the ambiguous 'any' cross-reference warning.
7575
Patch by Simão Afonso and Adam Turner.
76+
* #13272: The Python and JavaScript module directives now support
77+
the ``:no-index-entry:`` option.
78+
Patch by Adam Turner.
7679

7780
Bugs fixed
7881
----------

doc/usage/domains/index.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ the content should be the description.
4848

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

sphinx/domains/javascript.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ def _object_hierarchy_parts(self, sig_node: desc_signature) -> tuple[str, ...]:
155155
def add_target_and_index(
156156
self, name_obj: tuple[str, str], sig: str, signode: desc_signature
157157
) -> None:
158-
mod_name = self.env.ref_context.get('js:module')
159-
fullname = (mod_name + '.' if mod_name else '') + name_obj[0]
158+
mod_name = self.env.ref_context.get('js:module', '')
159+
fullname = (f'{mod_name}.' if mod_name else '') + name_obj[0]
160160
node_id = make_id(self.env, self.state.document, '', fullname)
161161
signode['ids'].append(node_id)
162162
self.state.document.note_explicit_target(signode)
@@ -165,11 +165,10 @@ def add_target_and_index(
165165
domain.note_object(fullname, self.objtype, node_id, location=signode)
166166

167167
if 'no-index-entry' not in self.options:
168-
indextext = self.get_index_text(mod_name, name_obj) # type: ignore[arg-type]
169-
if indextext:
168+
if index_text := self.get_index_text(mod_name, name_obj):
170169
self.indexnode['entries'].append((
171170
'single',
172-
indextext,
171+
index_text,
173172
node_id,
174173
'',
175174
None,
@@ -333,6 +332,7 @@ class JSModule(SphinxDirective):
333332
final_argument_whitespace = False
334333
option_spec: ClassVar[OptionSpec] = {
335334
'no-index': directives.flag,
335+
'no-index-entry': directives.flag,
336336
'no-contents-entry': directives.flag,
337337
'no-typesetting': directives.flag,
338338
'noindex': directives.flag,
@@ -365,9 +365,12 @@ def run(self) -> list[Node]:
365365
)
366366

367367
# The node order is: index node first, then target node
368-
indextext = _('%s (module)') % mod_name
369-
inode = addnodes.index(entries=[('single', indextext, node_id, '', None)])
370-
ret.append(inode)
368+
if 'no-index-entry' not in self.options:
369+
index_text = _('%s (module)') % mod_name
370+
inode = addnodes.index(
371+
entries=[('single', index_text, node_id, '', None)]
372+
)
373+
ret.append(inode)
371374
target = nodes.target('', '', ids=[node_id], ismod=True)
372375
self.state.document.note_explicit_target(target)
373376
ret.append(target)

sphinx/domains/python/__init__.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ class PyModule(SphinxDirective):
479479
'platform': lambda x: x,
480480
'synopsis': lambda x: x,
481481
'no-index': directives.flag,
482+
'no-index-entry': directives.flag,
482483
'no-contents-entry': directives.flag,
483484
'no-typesetting': directives.flag,
484485
'noindex': directives.flag,
@@ -520,10 +521,15 @@ def run(self) -> list[Node]:
520521

521522
# the platform and synopsis aren't printed; in fact, they are only
522523
# used in the modindex currently
523-
indextext = f'module; {modname}'
524-
inode = addnodes.index(entries=[('pair', indextext, node_id, '', None)])
525-
# The node order is: index node first, then target node.
526-
ret.extend((inode, target))
524+
525+
if 'no-index-entry' not in self.options:
526+
index_text = f'module; {modname}'
527+
inode = addnodes.index(
528+
entries=[('pair', index_text, node_id, '', None)]
529+
)
530+
# The node order is: index node first, then target node.
531+
ret.append(inode)
532+
ret.append(target)
527533
ret.extend(content_nodes)
528534
return ret
529535

sphinx/domains/python/_object.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@ def get_index_text(self, modname: str, name: tuple[str, str]) -> str:
409409
def add_target_and_index(
410410
self, name_cls: tuple[str, str], sig: str, signode: desc_signature
411411
) -> None:
412-
modname = self.options.get('module', self.env.ref_context.get('py:module'))
413-
fullname = (f'{modname}.' if modname else '') + name_cls[0]
412+
mod_name = self.options.get('module', self.env.ref_context.get('py:module'))
413+
fullname = (f'{mod_name}.' if mod_name else '') + name_cls[0]
414414
node_id = make_id(self.env, self.state.document, '', fullname)
415415
signode['ids'].append(node_id)
416416
self.state.document.note_explicit_target(signode)
@@ -425,11 +425,10 @@ def add_target_and_index(
425425
)
426426

427427
if 'no-index-entry' not in self.options:
428-
indextext = self.get_index_text(modname, name_cls)
429-
if indextext:
428+
if index_text := self.get_index_text(mod_name, name_cls):
430429
self.indexnode['entries'].append((
431430
'single',
432-
indextext,
431+
index_text,
433432
node_id,
434433
'',
435434
None,

sphinx/domains/rst.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ def add_target_and_index(
5757
domain.note_object(self.objtype, name, node_id, location=signode)
5858

5959
if 'no-index-entry' not in self.options:
60-
indextext = self.get_index_text(self.objtype, name)
61-
if indextext:
60+
if index_text := self.get_index_text(self.objtype, name):
6261
self.indexnode['entries'].append((
6362
'single',
64-
indextext,
63+
index_text,
6564
node_id,
6665
'',
6766
None,

tests/test_domains/test_domain_js.py

+19
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,25 @@ def test_no_index_entry(app):
326326
)
327327
assert_node(doctree[2], addnodes.index, entries=[])
328328

329+
text = '.. js:class:: f\n.. js:class:: g\n :no-index-entry:\n'
330+
doctree = restructuredtext.parse(app, text)
331+
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
332+
assert_node(
333+
doctree[0],
334+
addnodes.index,
335+
entries=[('single', 'f() (class)', 'f', '', None)],
336+
)
337+
assert_node(doctree[2], addnodes.index, entries=[])
338+
339+
text = '.. js:module:: f\n.. js:module:: g\n :no-index-entry:\n'
340+
doctree = restructuredtext.parse(app, text)
341+
assert_node(doctree, (addnodes.index, nodes.target, nodes.target))
342+
assert_node(
343+
doctree[0],
344+
addnodes.index,
345+
entries=[('single', 'f (module)', 'module-f', '', None)],
346+
)
347+
329348

330349
@pytest.mark.sphinx('html', testroot='root')
331350
def test_module_content_line_number(app):

tests/test_domains/test_domain_py.py

+9
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,15 @@ def test_no_index_entry(app):
836836
)
837837
assert_node(doctree[2], addnodes.index, entries=[])
838838

839+
text = '.. py:module:: f\n.. py:module:: g\n :no-index-entry:\n'
840+
doctree = restructuredtext.parse(app, text)
841+
assert_node(doctree, (addnodes.index, nodes.target, nodes.target))
842+
assert_node(
843+
doctree[0],
844+
addnodes.index,
845+
entries=[('pair', 'module; f', 'module-f', '', None)],
846+
)
847+
839848

840849
@pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names')
841850
def test_python_python_use_unqualified_type_names(app):

0 commit comments

Comments
 (0)