1818
1919from __future__ import annotations
2020
21- from typing import TYPE_CHECKING
21+ from textwrap import indent
22+ from typing import TYPE_CHECKING , Any , Literal
2223
2324from griffe ._internal .enumerations import DocstringSectionKind
2425from griffe ._internal .expressions import ExprTuple
2526
2627if TYPE_CHECKING :
2728 from collections .abc import Sequence
28- from typing import Any , Literal
2929
3030 from griffe ._internal .expressions import Expr
3131
3232
33+ DocstringStyle = Literal ["google" , "numpy" , "sphinx" , "auto" ]
34+ """The supported docstring styles (literal values of the Parser enumeration)."""
35+
36+
3337# Elements -----------------------------------------------
3438class DocstringElement :
3539 """This base class represents annotated, nameless elements."""
3640
37- def __init__ (self , * , description : str , annotation : str | Expr | None = None ) -> None :
41+ def __init__ (self , * , description : str , annotation : str | Expr | None = None , hardcoded : bool = True ) -> None :
3842 """Initialize the element.
3943
4044 Parameters:
41- annotation: The element annotation, if any.
4245 description: The element description.
46+ annotation: The element annotation, if any.
47+ hardcoded: Whether the annotation was hardcoded into the docstring.
4348 """
4449 self .description : str = description
4550 """The element description."""
4651 self .annotation : str | Expr | None = annotation
4752 """The element annotation."""
53+ self .hardcoded : bool = hardcoded
54+ """Whether the annotation was hardcoded into the docstring.
55+
56+ It could have been obtained via other means (e.g. type hints).
57+
58+ This helps to determine whether the annotation should be included
59+ when re-rendering a docstring section.
60+ """
4861
4962 def as_dict (self , ** kwargs : Any ) -> dict [str , Any ]: # noqa: ARG002
5063 """Return this element's data as a dictionary.
@@ -71,6 +84,7 @@ def __init__(
7184 description : str ,
7285 annotation : str | Expr | None = None ,
7386 value : str | Expr | None = None ,
87+ hardcoded : bool = True ,
7488 ) -> None :
7589 """Initialize the element.
7690
@@ -79,8 +93,9 @@ def __init__(
7993 description: The element description.
8094 annotation: The element annotation, if any.
8195 value: The element value, as a string.
96+ hardcoded: Whether the annotation was hardcoded into the docstring.
8297 """
83- super ().__init__ (description = description , annotation = annotation )
98+ super ().__init__ (description = description , annotation = annotation , hardcoded = hardcoded )
8499 self .name : str = name
85100 """The element name."""
86101 self .value : str | Expr | None = value
@@ -277,6 +292,12 @@ def as_dict(self, **kwargs: Any) -> dict[str, Any]:
277292 base ["title" ] = self .title
278293 return base
279294
295+ def render (self , style : DocstringStyle ) -> str :
296+ """Render the section as a string."""
297+ raise NotImplementedError (
298+ f"Rendering not implemented for sections '{ self .__class__ .__name__ } ' and style '{ style } '"
299+ )
300+
280301
281302class DocstringSectionText (DocstringSection ):
282303 """This class represents a text section."""
@@ -293,6 +314,10 @@ def __init__(self, value: str, title: str | None = None) -> None:
293314 super ().__init__ (title )
294315 self .value : str = value
295316
317+ def render (self , style : DocstringStyle ) -> str :
318+ """Render the section as a string."""
319+ return self .value
320+
296321
297322class DocstringSectionParameters (DocstringSection ):
298323 """This class represents a parameters section."""
@@ -309,6 +334,23 @@ def __init__(self, value: list[DocstringParameter], title: str | None = None) ->
309334 super ().__init__ (title )
310335 self .value : list [DocstringParameter ] = value
311336
337+ def render (self , style : DocstringStyle ) -> str :
338+ """Render the section as a string."""
339+ return {
340+ "google" : self .render_google ,
341+ "numpy" : self .render_numpy ,
342+ "sphinx" : self .render_sphinx ,
343+ }.get (style , super ().render )()
344+
345+ def render_google (self ) -> str :
346+ """Render the section in Google style."""
347+ lines = ["Parameters:" ]
348+ for param in self .value :
349+ annotation = f" ({ param .annotation } )" if param .annotation and param .hardcoded else ""
350+ lines .append (f" { param .name } { annotation } :" )
351+ lines .extend (indent (param .description , " " * 8 ).splitlines ())
352+ return "\n " .join (lines )
353+
312354
313355class DocstringSectionOtherParameters (DocstringSectionParameters ):
314356 """This class represents an other parameters section."""
0 commit comments