Skip to content

Commit 9579c8a

Browse files
committed
fixup! Add py:type directive and role
1 parent ce845f2 commit 9579c8a

File tree

6 files changed

+70
-18
lines changed

6 files changed

+70
-18
lines changed

doc/usage/domains/python.rst

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ The following directives are provided for module and class contents:
124124
.. rst:directive:: .. py:data:: name
125125
126126
Describes global data in a module, including both variables and values used
127-
as "defined constants." Class and object attributes are documented
128-
with :rst:dir:`py:attribute`. Type aliases are documented with
129-
:rst:dir:`py:type`.
127+
as "defined constants." Consider using :rst:dir:`py:type` for type
128+
aliases instead and :rst:dir:`py:attribute` for class variables and
129+
instance attributes.
130130

131131
.. rubric:: options
132132

@@ -259,7 +259,7 @@ The following directives are provided for module and class contents:
259259
260260
Describes an object data attribute. The description should include
261261
information about the type of the data to be expected and whether it may be
262-
changed directly. Type aliases are documented with :rst:dir:`py:type`.
262+
changed directly. Type aliases should be documented with :rst:dir:`py:type`.
263263

264264
.. rubric:: options
265265

@@ -318,17 +318,33 @@ The following directives are provided for module and class contents:
318318
319319
.. rst:directive:: .. py:type:: name
320320
321-
Describes a :ref:`type alias <python:type-aliases>`. A description of
322-
the type alias, such as the docstring can be, placed in the body of
323-
the directive.
321+
Describe a :ref:`type alias <python:type-aliases>`.
324322

325-
.. versionadded:: 7.3
323+
This directive supports an optional description body, e.g.::
324+
325+
.. code-block:: rst
326+
327+
.. py:type:: UInt64
328+
329+
Represent a 64-bit positive integer.
326330
327331
.. rubric:: options
328332

329-
.. rst:directive:option:: type: the type that the alias represents
333+
.. rst:directive:option:: canonical
330334
:type: text
331335
336+
The canonical type represented by this alias, e.g.::
337+
338+
.. code-block:: rst
339+
340+
.. py:type:: StrPattern
341+
342+
:canonical: str | re.Pattern[str]
343+
344+
Represent a regular expression or a compiled pattern.
345+
346+
.. versionadded:: 7.3
347+
332348
.. rst:directive:: .. py:method:: name(parameters)
333349
.. py:method:: name[type parameters](parameters)
334350

sphinx/domains/python/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,9 +393,9 @@ def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str:
393393
class PyTypeAlias(PyObject):
394394
"""Description of a type alias."""
395395

396-
option_spec: OptionSpec = PyObject.option_spec.copy()
396+
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
397397
option_spec.update({
398-
'value': directives.unchanged,
398+
'canonical': directives.unchanged,
399399
})
400400

401401
def get_signature_prefix(self, sig: str) -> list[nodes.Node]:
@@ -404,10 +404,10 @@ def get_signature_prefix(self, sig: str) -> list[nodes.Node]:
404404
def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]:
405405
fullname, prefix = super().handle_signature(sig, signode)
406406

407-
value = self.options.get('value')
408-
if value:
409-
annotations = _parse_annotation(value, self.env)
410-
signode += addnodes.desc_annotation(value, '',
407+
canonical = self.options.get('canonical')
408+
if canonical:
409+
annotations = _parse_annotation(canonical, self.env)
410+
signode += addnodes.desc_annotation(canonical, '',
411411
addnodes.desc_sig_space(),
412412
addnodes.desc_sig_punctuation('', '='),
413413
addnodes.desc_sig_space(),

tests/roots/test-domain-py/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ test-domain-py
88
module_option
99
abbr
1010
canonical
11+
type_alias

tests/roots/test-domain-py/module.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ module
6666
:type: typing.Literal[-2]
6767

6868
.. py:type:: MyType1
69-
:value: list[int | str]
69+
:canonical: list[int | str]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Type Alias
2+
==========
3+
4+
.. py:module:: module_two
5+
6+
.. py:class:: SomeClass
7+
8+
:py:type:`.MyAlias`
9+
:any:`MyAlias`
10+
:any:`module_one.MyAlias`
11+
12+
.. py:module:: module_one
13+
14+
.. py:type:: MyAlias
15+
:canonical: list[int | module_two.SomeClass]

tests/test_domains/test_domain_py_pyobject.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import pytest
56
from docutils import nodes
67

78
from sphinx import addnodes
@@ -365,12 +366,12 @@ def test_pyproperty(app):
365366
def test_pytypealias(app):
366367
text = (".. py:module:: example\n"
367368
".. py:type:: Alias1\n"
368-
" :value: list[str | int]\n"
369+
" :canonical: list[str | int]\n"
369370
"\n"
370371
".. py:class:: Class\n"
371372
"\n"
372373
" .. py:type:: Alias2\n"
373-
" :value: int\n")
374+
" :canonical: int\n")
374375
domain = app.env.get_domain('py')
375376
doctree = restructuredtext.parse(app, text)
376377
assert_node(doctree, (addnodes.index,
@@ -413,6 +414,25 @@ def test_pytypealias(app):
413414
assert domain.objects['example.Class.Alias2'] == ('index', 'example.Class.Alias2', 'type', False)
414415

415416

417+
@pytest.mark.sphinx('html', testroot='domain-py', freshenv=True)
418+
def test_domain_py_type_alias(app, status, warning):
419+
app.build(force_all=True)
420+
421+
content = (app.outdir / 'type_alias.html').read_text(encoding='utf8')
422+
assert ('<em class="property"><span class="pre">type</span><span class="w"> </span></em>'
423+
'<span class="sig-prename descclassname"><span class="pre">module_one.</span></span>'
424+
'<span class="sig-name descname"><span class="pre">MyAlias</span></span>'
425+
'<em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span>'
426+
'<span class="w"> </span><span class="pre">list</span>'
427+
'<span class="p"><span class="pre">[</span></span>'
428+
'<span class="pre">int</span><span class="w"> </span>'
429+
'<span class="p"><span class="pre">|</span></span><span class="w"> </span>'
430+
'<a class="reference internal" href="#module_two.SomeClass" title="module_two.SomeClass">'
431+
'<span class="pre">module_two.SomeClass</span></a>'
432+
'<span class="p"><span class="pre">]</span></span></em>' in content)
433+
assert warning.getvalue() == ''
434+
435+
416436
def test_pydecorator_signature(app):
417437
text = ".. py:decorator:: deco"
418438
domain = app.env.get_domain('py')

0 commit comments

Comments
 (0)