Skip to content

Commit

Permalink
give pybind11 classes a reasonable docstring.
Browse files Browse the repository at this point in the history
use cleandoc logic to determin dedent in docstring
  • Loading branch information
jcapriot committed Aug 18, 2024
1 parent 4b4d8ec commit b66c0bd
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
42 changes: 28 additions & 14 deletions mypy/stubgenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import inspect
import keyword
import os.path
import sys
from types import FunctionType, ModuleType
from typing import Any, Callable, Mapping

Expand Down Expand Up @@ -652,21 +653,34 @@ def generate_function_stub(

def _indent_docstring(self, docstring: str) -> str:
"""Fix indentation of docstring extracted from pybind11 or other binding generators."""
lines = docstring.splitlines(keepends=True)
# this follows inspect.cleandoc except it only changes the margins.
# it won't remove empty lines at the start or end.
# nor remove whitespace at the start of the first line.
# essentially it should do as little to the docstring as possible.

lines = docstring.expandtabs().split("\n")

# Find minimum indentation of any non-blank lines after first line.
margin = sys.maxsize
for line in lines[1:]:
content = len(line.lstrip(" "))
if content:
indent = len(line) - content
margin = min(margin, indent)

indent = self._indent + " "
if len(lines) > 1:
if not all(line.startswith(indent) or not line.strip() for line in lines):
# if the docstring is not indented, then indent all but the first line
for i, line in enumerate(lines[1:]):
if line.strip():
lines[i + 1] = indent + line
# if there's a trailing newline, add a final line to visually indent the quoted docstring
if lines[-1].endswith("\n"):
if len(lines) > 1:
lines.append(indent)
else:
lines[-1] = lines[-1][:-1]
return "".join(lines)
# Remove margin and set it to indent.
if margin < sys.maxsize:
for i in range(1, len(lines)):
dedent_line = lines[i][margin:]
# if the lile after dedent was not empty, add our indent
if dedent_line:
dedent_line = indent + dedent_line
lines[i] = dedent_line
if lines[-1] == "":
# if the last line was empty, indent it so the triple end quote is in a good spot.
lines[-1] = indent + lines[-1]
return "\n".join(lines)

def _fix_iter(
self, ctx: FunctionContext, inferred: list[FunctionSig], output: list[str]
Expand Down
4 changes: 2 additions & 2 deletions test-data/pybind11_fixtures/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ void bind_demo(py::module& m) {

// Classes
py::class_<Point> pyPoint(m, "Point");
py::enum_<Point::LengthUnit> pyLengthUnit(pyPoint, "LengthUnit");
py::enum_<Point::AngleUnit> pyAngleUnit(pyPoint, "AngleUnit");
py::enum_<Point::LengthUnit> pyLengthUnit(pyPoint, "LengthUnit", "Describes the length measurement units.");
py::enum_<Point::AngleUnit> pyAngleUnit(pyPoint, "AngleUnit", "Describes the angle measurement units.");

pyPoint
.def(py::init<>())
Expand Down

0 comments on commit b66c0bd

Please sign in to comment.