Skip to content

Commit 07df68d

Browse files
committedSep 17, 2023
Fix/enhance stubgen docstrings for functions, properties and types
Fixes #16114
1 parent 9b91524 commit 07df68d

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed
 

‎mypy/stubgenc.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ def generate_c_function_stub(
365365
if is_overloaded:
366366
imports.append("from typing import overload")
367367
if inferred:
368+
docstr = getattr(obj, "__doc__", None)
368369
for signature in inferred:
369370
args: list[str] = []
370371
for arg in signature.args:
@@ -458,6 +459,7 @@ def generate_c_property_stub(
458459
module: ModuleType | None = None,
459460
known_modules: list[str] | None = None,
460461
imports: list[str] | None = None,
462+
include_docstrings: bool = False,
461463
) -> None:
462464
"""Generate property stub using introspection of 'obj'.
463465
@@ -476,25 +478,39 @@ def infer_prop_type(docstr: str | None) -> str | None:
476478
else:
477479
return None
478480

479-
inferred = infer_prop_type(getattr(obj, "__doc__", None))
481+
docstr: str | None = getattr(obj, "__doc__", None)
482+
inferred = infer_prop_type(docstr)
480483
if not inferred:
481484
fget = getattr(obj, "fget", None)
482485
inferred = infer_prop_type(getattr(fget, "__doc__", None))
486+
docstr = getattr(fget, "__doc__", None) or docstr
483487
if not inferred:
484488
inferred = "Any"
485489

486490
if module is not None and imports is not None and known_modules is not None:
487491
inferred = strip_or_import(inferred, module, known_modules, imports)
488492

493+
if include_docstrings and docstr:
494+
# Quoted docstr
495+
docstr = mypy.util.quote_docstring(docstr.strip())
496+
# Indented docstr
497+
docstr = "\n ".join(docstr.split("\n"))
498+
489499
if is_static_property(obj):
490500
trailing_comment = " # read-only" if readonly else ""
491501
static_properties.append(f"{name}: ClassVar[{inferred}] = ...{trailing_comment}")
502+
if include_docstrings and docstr:
503+
static_properties.extend(docstr.split("\n"))
492504
else: # regular property
493505
if readonly:
494506
ro_properties.append("@property")
495507
ro_properties.append(f"def {name}(self) -> {inferred}: ...")
508+
if include_docstrings and docstr:
509+
ro_properties.extend(f" {docstr}".split("\n"))
496510
else:
497511
rw_properties.append(f"{name}: {inferred}")
512+
if include_docstrings and docstr:
513+
rw_properties.extend(docstr.split("\n"))
498514

499515

500516
def generate_c_type_stub(
@@ -561,6 +577,7 @@ def generate_c_type_stub(
561577
module=module,
562578
known_modules=known_modules,
563579
imports=imports,
580+
include_docstrings=include_docstrings,
564581
)
565582
elif is_c_type(value):
566583
generate_c_type_stub(
@@ -605,8 +622,19 @@ def generate_c_type_stub(
605622
)
606623
else:
607624
bases_str = ""
625+
626+
docstr: str | None = getattr(obj, "__doc__", None)
627+
if include_docstrings and docstr:
628+
# Quoted docstr
629+
docstr = mypy.util.quote_docstring(docstr.strip())
630+
# Indented docstr
631+
docstr = "\n ".join(docstr.split("\n"))
632+
# Add the docstr class type
633+
608634
if types or static_properties or rw_properties or methods or ro_properties:
609635
output.append(f"class {class_name}{bases_str}:")
636+
if include_docstrings and docstr:
637+
output.extend(f" {docstr}".split("\n"))
610638
for line in types:
611639
if (
612640
output
@@ -626,6 +654,8 @@ def generate_c_type_stub(
626654
output.append(f" {line}")
627655
else:
628656
output.append(f"class {class_name}{bases_str}: ...")
657+
if include_docstrings and docstr:
658+
output.extend(f" {docstr}".split("\n") + [""])
629659

630660

631661
def get_type_fullname(typ: type) -> str:

0 commit comments

Comments
 (0)