Skip to content

Accept Numpydoc underlines of any length, and of = - #178

Merged
rr- merged 1 commit into
mainfrom
rework/37-numpydoc-underlines
Nov 6, 2026
Merged

rr- merged 1 commit into
mainfrom
rework/37-numpydoc-underlines

Conversation

@rr-

@rr- rr- commented Nov 6, 2026

Copy link
Copy Markdown
Owner

A Numpydoc section title no longer needs an underline exactly as long as the title. Following napoleon, any underline of two or more -, or of two or more =, now starts the section, so

Parameters
---
x : int

and

Returns
=======
int

are read as sections and no longer end up in the long description. Auto-detection's "no fields at all" shortcut now also looks for = underlines, so a docstring like that gets detected as Numpydoc and not sent to ReST unparsed.

Headings that no section declares, such as Options, are unchanged: they still need a dash underline exactly as long as the title. That rule is what keeps a table's header row from being read as a heading.

Once more text read as sections, the round-trip invariant caught two returns that compose wrote in a form that read back differently:

  • A named return with an empty type, as in total :, was written as total, and that reads back as a type. It is now written total :.
  • An unnamed return with a colon on the first line of its type, as in : a: b, was written as a: b, and that reads back as a name and a type. It is now written : a: b.

A typed param with an empty name is also written without a space before its colon, since that space indented the line. The invariant exclusion lists are unchanged.

Case diffs

  • corpus/numpy/numpy.lib._histograms_impl._get_bin_edges: its Parameters / ========== and Returns / ======= were long description and are now three params and two returns. Detection changes from rest to numpydoc, and compose writes dash underlines.
  • New: numpydoc/underline_01 (short and long dashes), numpydoc/underline_02 (=, including detection), numpydoc/compose_returns_01 (the two returns above).

Parity against origin/main

origin differ compose only
case 4 of 1543 1
stdlib 0 of 7631 0
generated 201 of 20000 6

I spot-checked the generated parse differences. Each one has a declared title with a dash underline of a different length. The six that differ only in compose are the return and param forms listed above.

tools/parity.py itself crashes with a KeyError when printing an input that parses in the base but not in the tree, so I got these counts from a small script that calls its outputs().

Bench

Python 3.8, every ratio between 0.98 and 1.01.

A section title had to be underlined by exactly as many dashes as it
has characters, so "Parameters" over "---" or over "==========" stayed
in the long description. As in napoleon, an underline of two or more
dashes or equals signs now does, whatever its length. Auto-detection
looks for an underline of equals signs too, so it no longer takes such
a docstring for one without sections.

Headings no section declares still need an underline of dashes as long
as the title, which tells them from tables.

More text now reads as sections, which made compose show two ways a
return did not read back: a named return with an empty type, written
as its name alone and read back as its type, and an unnamed one with a
colon in its type, read back as a name and a type. Compose writes them
as "total :" and ": a: b". A param with no name is written with no
space before its colon, which indented it.
@rr- rr- self-assigned this Nov 6, 2026
@rr-
rr- merged commit b31fbb1 into main Nov 6, 2026
26 checks passed
@rr-
rr- deleted the rework/37-numpydoc-underlines 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