Skip to content

Commit 480630c

Browse files
picnixzAA-Turner
andauthored
Support PEP 695 and PEP 696 syntax in the Python domain (#11444)
* Generic classes can be documented with ``.. py:class::`` using PEP 695 syntax: .. code:: rst .. py:class:: Sequence[T] * Generic functions can be documented with ``.. py:function::`` using PEP 695 syntax: .. code:: rst .. py:function:: foo[T](x: T) * Default values for type bounds are supported. Co-authored-by: Adam Turner <[email protected]>
1 parent f5aadc1 commit 480630c

File tree

15 files changed

+934
-45
lines changed

15 files changed

+934
-45
lines changed

CHANGES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ Features added
3434
* #11157: Keep the ``translated`` attribute on translated nodes.
3535
* #11451: Improve the traceback displayed when using :option:`sphinx-build -T`
3636
in parallel builds. Patch by Bénédikt Tran
37+
* #11438: Add support for the :rst:dir:`py:class` and :rst:dir:`py:function`
38+
directives for PEP 695 (generic classes and functions declarations) and
39+
PEP 696 (default type parameters). Multi-line support (#11011) is enabled
40+
for type parameters list and can be locally controlled on object description
41+
directives, e.g., :rst:dir:`py:function:single-line-type-parameter-list`.
42+
Patch by Bénédikt Tran.
3743

3844
Bugs fixed
3945
----------

doc/latex.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,7 @@ Macros
14641464
``\sphinxtermref``; ``\emph{#1}``
14651465
``\sphinxsamedocref``; ``\emph{#1}``
14661466
``\sphinxparam``; ``\emph{#1}``
1467+
``\sphinxtypeparam``; ``\emph{#1}``
14671468
``\sphinxoptional``; ``[#1]`` with larger brackets, see source
14681469

14691470
.. versionadded:: 1.4.5
@@ -1485,6 +1486,12 @@ Macros
14851486
signatures (see :confval:`maximum_signature_line_length`). It defaults
14861487
to ``\texttt{,}`` to make these end-of-line separators more distinctive.
14871488

1489+
Signatures of Python functions are rendered as ``name<space>(parameters)``
1490+
or ``name<space>[type parameters]<space>(parameters)`` (see :pep:`695`)
1491+
where the length of ``<space>`` is set to ``0pt`` by default.
1492+
This can be changed via ``\setlength{\sphinxsignaturelistskip}{1ex}``
1493+
for instance.
1494+
14881495
- More text styling:
14891496

14901497
.. csv-table::

doc/usage/configuration.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,9 +3025,24 @@ Options for the Python domain
30253025

30263026
.. confval:: python_maximum_signature_line_length
30273027

3028-
If a signature's length in characters exceeds the number set, each
3029-
argument will be displayed on an individual logical line. This is a
3030-
domain-specific setting, overriding :confval:`maximum_signature_line_length`.
3028+
If a signature's length in characters exceeds the number set,
3029+
each argument or type parameter will be displayed on an individual logical line.
3030+
This is a domain-specific setting,
3031+
overriding :confval:`maximum_signature_line_length`.
3032+
3033+
For the Python domain, the signature length depends on whether
3034+
the type parameters or the list of arguments are being formatted.
3035+
For the former, the signature length ignores the length of the arguments list;
3036+
for the latter, the signature length ignores the length of
3037+
the type parameters list.
3038+
3039+
For instance, with `python_maximum_signature_line_length = 20`,
3040+
only the list of type parameters will be wrapped
3041+
while the arguments list will be rendered on a single line
3042+
3043+
.. code:: rst
3044+
3045+
.. py:function:: add[T: VERY_LONG_SUPER_TYPE, U: VERY_LONG_SUPER_TYPE](a: T, b: U)
30313046
30323047
.. versionadded:: 7.1
30333048

doc/usage/restructuredtext/domains.rst

Lines changed: 91 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,16 @@ declarations:
192192
The following directives are provided for module and class contents:
193193

194194
.. rst:directive:: .. py:function:: name(parameters)
195+
.. py:function:: name[type parameters](parameters)
195196
196-
Describes a module-level function. The signature should include the
197-
parameters as given in the Python function definition, see :ref:`signatures`.
197+
Describes a module-level function.
198+
The signature should include the parameters,
199+
together with optional type parameters,
200+
as given in the Python function definition, see :ref:`signatures`.
198201
For example::
199202

200-
.. py:function:: Timer.repeat(repeat=3, number=1000000)
203+
.. py:function:: Timer.repeat(repeat=3, number=1_000_000)
204+
.. py:function:: add[T](a: T, b: T) -> T
201205

202206
For methods you should use :rst:dir:`py:method`.
203207

@@ -240,6 +244,15 @@ The following directives are provided for module and class contents:
240244
241245
.. versionadded:: 7.1
242246
247+
.. rst:directive:option:: single-line-type-parameter-list
248+
:type: no value
249+
250+
Ensure that the function's type parameters are emitted on a single
251+
logical line, overriding :confval:`python_maximum_signature_line_length`
252+
and :confval:`maximum_signature_line_length`.
253+
254+
.. versionadded:: 7.1
255+
243256
244257
.. rst:directive:: .. py:data:: name
245258
@@ -274,9 +287,12 @@ The following directives are provided for module and class contents:
274287
the module specified by :rst:dir:`py:currentmodule`.
275288
276289
.. rst:directive:: .. py:exception:: name
290+
.. py:exception:: name(parameters)
291+
.. py:exception:: name[type parmeters](parameters)
277292
278-
Describes an exception class. The signature can, but need not include
279-
parentheses with constructor arguments.
293+
Describes an exception class.
294+
The signature can, but need not include parentheses with constructor arguments,
295+
or may optionally include type parameters (see :pep:`695`).
280296

281297
.. rubric:: options
282298

@@ -293,12 +309,28 @@ The following directives are provided for module and class contents:
293309
Describe the location where the object is defined. The default value is
294310
the module specified by :rst:dir:`py:currentmodule`.
295311
312+
.. rst:directive:option:: single-line-parameter-list
313+
:type: no value
314+
315+
See :rst:dir:`py:class:single-line-parameter-list`.
316+
317+
.. versionadded:: 7.1
318+
319+
.. rst:directive:option:: single-line-type-parameter-list
320+
:type: no value
321+
322+
See :rst:dir:`py:class:single-line-type-parameter-list`.
323+
324+
.. versionadded:: 7.1
325+
296326
.. rst:directive:: .. py:class:: name
297327
.. py:class:: name(parameters)
328+
.. py:class:: name[type parmeters](parameters)
298329
299-
Describes a class. The signature can optionally include parentheses with
300-
parameters which will be shown as the constructor arguments. See also
301-
:ref:`signatures`.
330+
Describes a class.
331+
The signature can optionally include type parameters (see :pep:`695`)
332+
or parentheses with parameters which will be shown as the constructor arguments.
333+
See also :ref:`signatures`.
302334

303335
Methods and attributes belonging to the class should be placed in this
304336
directive's body. If they are placed outside, the supplied name should
@@ -348,6 +380,13 @@ The following directives are provided for module and class contents:
348380
349381
.. versionadded:: 7.1
350382
383+
.. rst:directive:option:: single-line-type-parameter-list
384+
:type: no value
385+
386+
Ensure that the class type parameters are emitted on a single logical
387+
line, overriding :confval:`python_maximum_signature_line_length` and
388+
:confval:`maximum_signature_line_length`.
389+
351390
.. rst:directive:: .. py:attribute:: name
352391
353392
Describes an object data attribute. The description should include
@@ -410,6 +449,7 @@ The following directives are provided for module and class contents:
410449
the module specified by :rst:dir:`py:currentmodule`.
411450
412451
.. rst:directive:: .. py:method:: name(parameters)
452+
.. py:method:: name[type parameters](parameters)
413453
414454
Describes an object method. The parameters should not include the ``self``
415455
parameter. The description should include similar information to that
@@ -469,6 +509,15 @@ The following directives are provided for module and class contents:
469509
470510
.. versionadded:: 7.1
471511
512+
.. rst:directive:option:: single-line-type-parameter-list
513+
:type: no value
514+
515+
Ensure that the method's type parameters are emitted on a single logical
516+
line, overriding :confval:`python_maximum_signature_line_length` and
517+
:confval:`maximum_signature_line_length`.
518+
519+
.. versionadded:: 7.2
520+
472521
.. rst:directive:option:: staticmethod
473522
:type: no value
474523
@@ -478,19 +527,22 @@ The following directives are provided for module and class contents:
478527
479528
480529
.. rst:directive:: .. py:staticmethod:: name(parameters)
530+
.. py:staticmethod:: name[type parameters](parameters)
481531
482532
Like :rst:dir:`py:method`, but indicates that the method is a static method.
483533

484534
.. versionadded:: 0.4
485535

486536
.. rst:directive:: .. py:classmethod:: name(parameters)
537+
.. py:classmethod:: name[type parameters](parameters)
487538
488539
Like :rst:dir:`py:method`, but indicates that the method is a class method.
489540

490541
.. versionadded:: 0.6
491542

492543
.. rst:directive:: .. py:decorator:: name
493544
.. py:decorator:: name(parameters)
545+
.. py:decorator:: name[type parameters](parameters)
494546
495547
Describes a decorator function. The signature should represent the usage as
496548
a decorator. For example, given the functions
@@ -531,8 +583,18 @@ The following directives are provided for module and class contents:
531583
532584
.. versionadded:: 7.1
533585
586+
.. rst:directive:option:: single-line-type-parameter-list
587+
:type: no value
588+
589+
Ensure that the decorator's type parameters are emitted on a single
590+
logical line, overriding :confval:`python_maximum_signature_line_length`
591+
and :confval:`maximum_signature_line_length`.
592+
593+
.. versionadded:: 7.2
594+
534595
.. rst:directive:: .. py:decoratormethod:: name
535596
.. py:decoratormethod:: name(signature)
597+
.. py:decoratormethod:: name[type parameters](signature)
536598
537599
Same as :rst:dir:`py:decorator`, but for decorators that are methods.
538600

@@ -561,6 +623,27 @@ argument support), you can use brackets to specify the optional parts:
561623

562624
It is customary to put the opening bracket before the comma.
563625

626+
Python 3.12 introduced *type parameters*, which are type variables
627+
declared directly within the class or function definition:
628+
629+
.. code:: python
630+
631+
class AnimalList[AnimalT](list[AnimalT]):
632+
...
633+
634+
def add[T](a: T, b: T) -> T:
635+
return a + b
636+
637+
The corresponding reStructuredText documentation would be:
638+
639+
.. code:: rst
640+
641+
.. py:class:: AnimalList[AnimalT]
642+
643+
.. py:function:: add[T](a: T, b: T) -> T
644+
645+
See :pep:`695` and :pep:`696` for details and the full specification.
646+
564647
.. _info-field-lists:
565648

566649
Info field lists

sphinx/addnodes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,27 @@ def astext(self):
258258
return f'({super().astext()})'
259259

260260

261+
class desc_type_parameter_list(nodes.Part, nodes.Inline, nodes.FixedTextElement):
262+
"""Node for a general type parameter list.
263+
264+
As default the type parameters list is written in line with the rest of the signature.
265+
Set ``multi_line_parameter_list = True`` to describe a multi-line type parameters list.
266+
In that case each type parameter will then be written on its own, indented line.
267+
"""
268+
child_text_separator = ', '
269+
270+
def astext(self):
271+
return f'[{super().astext()}]'
272+
273+
261274
class desc_parameter(nodes.Part, nodes.Inline, nodes.FixedTextElement):
262275
"""Node for a single parameter."""
263276

264277

278+
class desc_type_parameter(nodes.Part, nodes.Inline, nodes.FixedTextElement):
279+
"""Node for a single type parameter."""
280+
281+
265282
class desc_optional(nodes.Part, nodes.Inline, nodes.FixedTextElement):
266283
"""Node for marking optional parts of the parameter list."""
267284
child_text_separator = ', '
@@ -537,7 +554,9 @@ def setup(app: Sphinx) -> dict[str, Any]:
537554
app.add_node(desc_type)
538555
app.add_node(desc_returns)
539556
app.add_node(desc_parameterlist)
557+
app.add_node(desc_type_parameter_list)
540558
app.add_node(desc_parameter)
559+
app.add_node(desc_type_parameter)
541560
app.add_node(desc_optional)
542561
app.add_node(desc_annotation)
543562

0 commit comments

Comments
 (0)