22
33from __future__ import annotations
44
5- from typing import TYPE_CHECKING
5+ from textwrap import indent
6+ from typing import TYPE_CHECKING , Any , Literal
67
78from _griffe .enumerations import DocstringSectionKind
89
910if TYPE_CHECKING :
10- from typing import Any , Literal
11-
1211 from _griffe .expressions import Expr
1312
1413
14+ DocstringStyle = Literal ["google" , "numpy" , "sphinx" , "auto" ]
15+ """The supported docstring styles (literal values of the Parser enumeration)."""
16+
17+
1518# Elements -----------------------------------------------
1619class DocstringElement :
1720 """This base class represents annotated, nameless elements."""
1821
19- def __init__ (self , * , description : str , annotation : str | Expr | None = None ) -> None :
22+ def __init__ (self , * , description : str , annotation : str | Expr | None = None , hardcoded : bool = True ) -> None :
2023 """Initialize the element.
2124
2225 Parameters:
23- annotation: The element annotation, if any.
2426 description: The element description.
27+ annotation: The element annotation, if any.
28+ hardcoded: Whether the annotation was hardcoded into the docstring.
2529 """
2630 self .description : str = description
2731 """The element description."""
2832 self .annotation : str | Expr | None = annotation
2933 """The element annotation."""
34+ self .hardcoded : bool = hardcoded
35+ """Whether the annotation was hardcoded into the docstring.
36+
37+ It could have been obtained via other means (e.g. type hints).
38+
39+ This helps to determine whether the annotation should be included
40+ when re-rendering a docstring section.
41+ """
3042
3143 def as_dict (self , ** kwargs : Any ) -> dict [str , Any ]: # noqa: ARG002
3244 """Return this element's data as a dictionary.
@@ -53,6 +65,7 @@ def __init__(
5365 description : str ,
5466 annotation : str | Expr | None = None ,
5567 value : str | None = None ,
68+ hardcoded : bool = True ,
5669 ) -> None :
5770 """Initialize the element.
5871
@@ -61,8 +74,9 @@ def __init__(
6174 description: The element description.
6275 annotation: The element annotation, if any.
6376 value: The element value, as a string.
77+ hardcoded: Whether the annotation was hardcoded into the docstring.
6478 """
65- super ().__init__ (description = description , annotation = annotation )
79+ super ().__init__ (description = description , annotation = annotation , hardcoded = hardcoded )
6680 self .name : str = name
6781 """The element name."""
6882 self .value : str | None = value
@@ -217,6 +231,12 @@ def as_dict(self, **kwargs: Any) -> dict[str, Any]:
217231 base ["title" ] = self .title
218232 return base
219233
234+ def render (self , style : DocstringStyle ) -> str :
235+ """Render the section as a string."""
236+ raise NotImplementedError (
237+ f"Rendering not implemented for sections '{ self .__class__ .__name__ } ' and style '{ style } '"
238+ )
239+
220240
221241class DocstringSectionText (DocstringSection ):
222242 """This class represents a text section."""
@@ -233,6 +253,10 @@ def __init__(self, value: str, title: str | None = None) -> None:
233253 super ().__init__ (title )
234254 self .value : str = value
235255
256+ def render (self , style : DocstringStyle ) -> str :
257+ """Render the section as a string."""
258+ return self .value
259+
236260
237261class DocstringSectionParameters (DocstringSection ):
238262 """This class represents a parameters section."""
@@ -249,6 +273,23 @@ def __init__(self, value: list[DocstringParameter], title: str | None = None) ->
249273 super ().__init__ (title )
250274 self .value : list [DocstringParameter ] = value
251275
276+ def render (self , style : DocstringStyle ) -> str :
277+ """Render the section as a string."""
278+ return {
279+ "google" : self .render_google ,
280+ "numpy" : self .render_numpy ,
281+ "sphinx" : self .render_sphinx ,
282+ }.get (style , super ().render )()
283+
284+ def render_google (self ) -> str :
285+ """Render the section in Google style."""
286+ lines = ["Parameters:" ]
287+ for param in self .value :
288+ annotation = f" ({ param .annotation } )" if param .annotation and param .hardcoded else ""
289+ lines .append (f" { param .name } { annotation } :" )
290+ lines .extend (indent (param .description , " " * 8 ).splitlines ())
291+ return "\n " .join (lines )
292+
252293
253294class DocstringSectionOtherParameters (DocstringSectionParameters ):
254295 """This class represents an other parameters section."""
0 commit comments