File: set-docstring-styles.md

package info (click to toggle)
python-griffe 1.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,292 kB
  • sloc: python: 17,202; makefile: 47; sh: 24; javascript: 13
file content (132 lines) | stat: -rw-r--r-- 4,657 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Setting the right docstring style for every docstring

Griffe attaches the specified docstring style and parsing options to each object in the tree of the package(s) you load. If your package(s) use several docstring styles, some of these objects will have the wrong style attached to them. This is problematic because other Griffe extensions rely on this attached style to parse docstrings and modify them. We plan to alleviate this limitation in the future (see [issue-340](https://github.com/mkdocstrings/griffe/issues/340)), but the most robust thing you can do is to make sure each object has the *right style* attached, as easly as possible, so that other extensions can work without issue.

There are currently two ways to make sure objects have the right docstring style attached as early as possible:

1. Use the [`auto` docstring style](https://mkdocstrings.github.io/griffe/reference/docstrings/#auto-style). Griffe will use regular expressions to infer the docstring style used. 100% accuracy is impossible to achieve, so it's possible that you get incorrect styles for some objects.
2. Write and use a custom Griffe extension.

This how-to provides a few extension-based solutions to correctly set docstring styles in your packages. **Just make sure to enable these extensions in first position.**

## Markup comment

Depending on the markup you use in docstrings, you can add a comment that tells Griffe which docstring style to use.

=== "Markdown"

    ```python
    def function():
        """Summary.

        Body.

        <!-- style: google -->
        """
    ```

=== "reStructuredText"

    ```python
    def function():
        """Summary.

        Body.

        .. style: google
        """
    ```

Your Griffe extension can then use regular expressions to search for such comments. For example with Markdown (HTML) comments:

```python
import re
import griffe


class ApplyDocstringStyle(griffe.Extension):
    def __init__(self, regex: str = "<!-- style: (google|numpy|sphinx) -->") -> None:
         self.regex = re.compile(regex)

    def on_instance(self, *, obj: griffe.Object, **kwargs) -> None:
        if obj.docstring:
            if match := self.regex.search(obj.docstring.value):
                obj.docstring.parser = match.group(1)
```

## Python comment

You could also decide to add a trailing comment to your docstrings to indicate which style to use.

```python
def function():
    """Summary.

    Body.
    """  # style: google
```

Your extension can then pick up this comment to assign the right style:

```python
import re
import griffe


class ApplyDocstringStyle(griffe.Extension):
    def __init__(self, regex: str = ".*# style: (google|numpy|sphinx)$") -> None:
         self.regex = re.compile(regex)

    def on_instance(self, *, obj: griffe.Object, **kwargs) -> None:
        if obj.docstring:
            if match := self.regex.search(obj.docstring.source):
                obj.docstring.parser = match.group(1)
```

## Explicit configuration

Finally, you could decide to map a list of objects to the docstring style they should use. Your extension can either accept options, or it could hard-code that list:

```python
import griffe
from fnmatch import fnmatch

class ApplyDocstringStyle(griffe.Extension):
    def __init__(self, config: dict[str, str]):
        self.instances = {}
        self.globs = {}
        for key, value in config.items():
            if "*" in key:
                self.globs[key] = value
            else:
                self.instances[key] = value

    def on_instance(self, *, obj: griffe.Object, **kwargs) -> None:
        if obj.path in self.instances:
            if obj.docstring:
                obj.docsring.parser = self.instances[obj.path]
         else:
             for pattern, style in self.globs:
                 if fnmatch(obj.path, pattern):
                     if obj.docstring:
                         obj.docstring.parser = style
```

Example configuration in MkDocs:

```yaml
plugins:
- mkdocstrings:
    handlers:
      python:
        options:
          extensions:
          - your_griffe_extension.py:
              config:
                path.to.obj1: google
                path.to.obj2: numpy
                path.to.obj3.*: sphinx
                path.to.obj4*: google
```

The benefit of this last solution is that it works for code you don't have control over. An alternative solution is to use the [griffe-autodocstringstyle extension](https://mkdocstrings.github.io/griffe/extensions/official/autodocstringstyle/), which automatically assigns the `auto` style to all objects coming from sources found in a virtual environment.