Skip to content

Read ReST ivar, var and cvar fields as attributes - #172

Merged
rr- merged 1 commit into
mainfrom
rework/34-rest-vartypes
Nov 6, 2026
Merged

rr- merged 1 commit into
mainfrom
rework/34-rest-vartypes

Conversation

@rr-

@rr- rr- commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Sphinx documents attributes with :ivar:, :var: and :cvar: fields, typed by :vartype:. ReST parsed them as plain text items, so they were missing from Docstring.attrs, and :vartype: was a text item too. Epydoc already reads @ivar as an attribute.

Short.

:ivar a: The a.
:vartype a: int

Before: DocstringMeta(kind=Kind.TEXT, key='ivar', name='a', description='The a.') and DocstringMeta(kind=Kind.TEXT, key='vartype', name='a', description='int').
After: DocstringParam(kind=Kind.ATTRIBUTE, key='ivar', arg_name='a', type_name='int', description='The a.').

:vartype x: types attributes the way :type x: types params, through _fields.assign_types, which takes a new vartypes table. Only attributes take from it, and an attribute of a name with no :vartype: still takes from :type:, so :attribute x: with :type x: keeps working. A :param x: and an :ivar x: of the same name each get their own type. A :vartype: that no attribute takes is an attribute of its own, as a lone :type: is a param.

An empty :type x: no longer gives x the type ''. Ignoring it completely would drop the name when nothing else mentions it, which the no-text-dropped invariant test catches, so a lone empty :type y: still makes a param y, now with no type.

Compose: an attribute keyed ivar, var or cvar is written back with that field name, and its type with :vartype: when it doesn't fit inline. Without this, :ivar a: would compose as :attribute a: and read back with another key. Attributes with any other key, such as the ones Google and Numpydoc give, still compose as :attribute: and :type:. Since Epydoc keys its attributes ivar, var and cvar too, converting Epydoc to ReST now writes :ivar a: instead of :attribute a:.

test_kinds.py::test_sub_kinds now expects :ivar to be an attribute.

Parity against origin/main: 926 of 29,149 docstrings differ, 18 from the case files and 908 generated, none from the stdlib.

  • 4 case inputs differ in parse REST/parse AUTO and their composes: the three new rest/attribute_fields_* cases and convert/rest-params, whose :ivar z: is now an attribute. Its Google and Numpydoc output stays the same.
  • The other 14 case and all 908 generated ones differ only in compose EPYDOC REST and compose AUTO REST (where auto picks Epydoc). There, @ivar, @var and @cvar now compose as :ivar:, :var: and :cvar: instead of :attribute:, and their types as :vartype: instead of :type:. With those names swapped back, every one matches main.

Bench (just bench): parse rest 93.0 ms on main vs 92.4 ms (0.99x), compose rest 1.00x, other workloads 0.99x to 1.00x.

@rr- rr- self-assigned this Nov 6, 2026
The :ivar:, :var: and :cvar: fields Sphinx documents attributes with
were text items in ReST, while Epydoc already read @ivar as an
attribute. Read them as params of kind ATTRIBUTE, and read :vartype x:
as their type, as :type x: is of params: _fields.assign_types takes the
new vartypes, which only attributes take, an attribute of a name with
none taking from types as before. A :vartype: that no attribute takes
is an attribute of its own, as a lone :type: is a param.

A :type x: field with no type no longer gives x an empty type. One for
a name that no other field gives still makes a param, with no type, so
that the name is kept.

Compose writes these attributes back with their own field names, and
their types with :vartype:, so they read back the same. Epydoc's @ivar,
@var and @cvar now convert to them too. An attribute with another key,
such as one from Google, keeps :attribute: and :type:.
@rr-
rr- force-pushed the rework/34-rest-vartypes branch from 9f20852 to df29541 Compare November 6, 2026 18:53
@rr-
rr- merged commit 217e7cf into main Nov 6, 2026
25 checks passed
@rr-
rr- deleted the rework/34-rest-vartypes branch November 6, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant