Repository navigation
v2.7.1: malformed expanded docstrings and incorrect subplots parameter documentation #835
Description
Description
Several public docstrings in UltraPlot 2.7.1 have malformed indentation or incorrect parameter documentation. I verified this against the official PyPI wheel (ultraplot-2.7.1-py3-none-any.whl, with its SHA256 checked against PyPI metadata), an installed 2.7.1 package, and the v2.7.1 GitHub source.
-
Expanded docstrings have inconsistent indentation in the distributed package. This affects
ultraplot.figure,ultraplot.subplot, andultraplot.subplots; I also observed it inFigure.__init__andGridSpec.__init__. Section headings and the first parameter retain the surrounding source indentation, while subsequent lines from the inserted snippet are dedented. For example, the first parameter and its description infigure()both have four leading spaces, but the next parameter has none.inspect.getdoc()does not repair this. Passing the installed UI docstrings through Sphinx'sNumpyDocstringparser leaves their indented sections unparsed. -
The
projectionparameter name and type are split onto separate, equally indented lines. The shared snippet containsprojection :followed bystr, ...on the next line, instead of one NumPy-style parameter declaration. This is present in the source snippet as well as the installed docstrings forsubplots()andFigure.subplots(). -
The
orderdescription reverses C/F ordering. The shared subplot snippet describesCas column-major andFas row-major. The implementation and actual subplot positions instead useCfor row-major andFfor column-major.
The latter two are issues in shared source snippets, separate from the distribution-time indentation problem. Single-line Python string literals with escaped newlines are valid docstrings; the issue is their resulting content and structure.
Steps to reproduce
With UltraPlot 2.7.1 installed:
import inspect
import platform
import matplotlib
matplotlib.use("Agg")
import numpy as np
import ultraplot as uplt
print("Python:", platform.python_version())
print("UltraPlot:", uplt.__version__)
print("Matplotlib:", matplotlib.__version__)
print("NumPy:", np.__version__)
for name in ("figure", "subplot", "subplots"):
doc = inspect.getdoc(getattr(uplt, name)) or ""
print(f"\n{name}:")
for line in doc.splitlines()[:12]:
print(repr(line))
lines = (inspect.getdoc(uplt.subplots) or "").splitlines()
index = lines.index("projection :")
print("\nprojection declaration:", repr("\n".join(lines[index:index + 2])))
for order in ("C", "F"):
fig, axs = uplt.subplots(nrows=2, ncols=2, order=order)
slots: list[tuple[int, int]] = []
for ax in axs:
spec = ax.get_subplotspec()
slots.append((spec.rowspan.start, spec.colspan.start))
print(order, slots)
uplt.close(fig)Actual behavior includes this excerpt for figure():
' Parameters'
' ----------'
' refnum : int, optional'
' The reference subplot number. The `refwidth`, `refheight`, and `refaspect`'
The following refaspect declaration has zero leading spaces. The projection declaration is:
'projection :\nstr, `cartopy.crs.Projection`, or `~mpl_toolkits.basemap.Basemap`, optional'
The actual subplot positions are:
C [(0, 0), (0, 1), (1, 0), (1, 1)]
F [(0, 0), (1, 0), (0, 1), (1, 1)]
Expected behavior: section headings and parameter declarations should align at column zero after docstring normalization, with descriptions indented beneath them. projection and its type should be on the same declaration line. The order documentation should say row-major for C and column-major for F.
Source investigation
- The UI functions use shared snippet placeholders in the v2.7.1 source. Executing that source with the snippet decorator produces correctly aligned UI docstrings, unlike the installed expanded literals.
- The build-time expander substitutes into raw AST string values before normalization. The runtime snippet manager normalizes with
inspect.getdoc()before substitution. Forfigure(), expanding the raw source docstring and then applyinginspect.cleandoc()reproduces the installed__doc__exactly. Normalizing before expansion produces the correctly aligned version. This appears to explain the indentation discrepancy. - The projection snippet contains the split declaration.
- The subplot parameter snippet contains the reversed C/F description; the implementation uses NumPy's
reshape(..., order=order).
It may help to preserve normalize-before-substitute semantics when materializing docstrings, and extend the installed-docstring check to validate section/parameter indentation in addition to checking for unresolved placeholders.
Equivalent steps in matplotlib
Not applicable: this concerns UltraPlot's shared docstrings and package-build expansion, rather than Matplotlib plotting behavior.
Ultra version
Reproduced on macOS arm64 with Python 3.14.7, UltraPlot 2.7.1, Matplotlib 3.11.2, and NumPy 2.5.3.
Activity
cvanelteren commentedon Oct 5, 2026
Running the code I get
cvanelteren commentedon Oct 5, 2026
I need to check the stubs because I think in general the existing docstrings are not numpy compliant.
cvanelteren commentedon Oct 6, 2026
I will draft a new bump @munechika-koyo
munechika-koyo commentedon Oct 6, 2026
Thank you for the prompt fix! @cvanelteren
cvanelteren commentedon Oct 6, 2026
pypi seems to return a 503 for some reason so the fix should be up in the next few days.
munechika-koyo commentedon Oct 6, 2026
It looks like the docstrings still aren't being reconstructed correctly.
I attached the corresponding file that was retrieved from the artifact created by CI: https://github.com/Ultraplot/UltraPlot/actions/runs/37408080333/job/112116854011
ui.py
cvanelteren commentedon Oct 6, 2026
2.7.2 wasn't uploaded yet. From a local wheel build they looked correct, what ar eyou seeing?
munechika-koyo commentedon Oct 6, 2026
I am seeing files in this artifact: https://github.com/Ultraplot/UltraPlot/actions/runs/37408080333/artifacts/11386869809
munechika-koyo commentedon Oct 6, 2026
I will try to add more modifications to fix/issue-835-docstrigns branch locally, then push them to the remote or create a new PR.