docstringify 0.1.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {docstringify-0.1.1 → docstringify-0.3.0}/PKG-INFO +36 -10
- {docstringify-0.1.1 → docstringify-0.3.0}/README.md +34 -8
- {docstringify-0.1.1 → docstringify-0.3.0}/pyproject.toml +1 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify/__init__.py +1 -1
- docstringify-0.3.0/src/docstringify/cli.py +96 -0
- docstringify-0.3.0/src/docstringify/converters/__init__.py +11 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify/converters/base.py +25 -3
- docstringify-0.3.0/src/docstringify/converters/google.py +44 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify/converters/numpydoc.py +8 -10
- docstringify-0.1.1/src/docstringify/visitor.py → docstringify-0.3.0/src/docstringify/docstring_generator.py +16 -55
- docstringify-0.3.0/src/docstringify/exceptions.py +6 -0
- docstringify-0.3.0/src/docstringify/transformer.py +53 -0
- docstringify-0.3.0/src/docstringify/visitor.py +79 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/PKG-INFO +36 -10
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/SOURCES.txt +4 -0
- docstringify-0.1.1/src/docstringify/cli.py +0 -71
- docstringify-0.1.1/src/docstringify/converters/__init__.py +0 -1
- {docstringify-0.1.1 → docstringify-0.3.0}/.github/dependabot.yml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.github/release.yml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.github/workflows/ci.yml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.github/workflows/pypi-publish.yml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.gitignore +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.pre-commit-config.yaml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/.pre-commit-hooks.yaml +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/LICENSE +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/setup.cfg +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify/__main__.py +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify/components.py +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/dependency_links.txt +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/entry_points.txt +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/requires.txt +0 -0
- {docstringify-0.1.1 → docstringify-0.3.0}/src/docstringify.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docstringify
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Flag missing docstrings and, optionally, generate them from signatures and type annotations.
|
|
5
5
|
Author-email: Stefanie Molin <docstringify@stefaniemolin.com>
|
|
6
6
|
License: MIT License
|
|
@@ -28,7 +28,7 @@ License: MIT License
|
|
|
28
28
|
Project-URL: Documentation, https://github.com/stefmolin/docstringify
|
|
29
29
|
Project-URL: Homepage, https://github.com/stefmolin/docstringify
|
|
30
30
|
Project-URL: Source, https://github.com/stefmolin/docstringify
|
|
31
|
-
Keywords: ast,docstring generation,numpydoc-style docstring,pre-commit
|
|
31
|
+
Keywords: ast,docstring generation,google-style docstring,numpydoc-style docstring,pre-commit
|
|
32
32
|
Classifier: Development Status :: 3 - Alpha
|
|
33
33
|
Classifier: License :: OSI Approved :: MIT License
|
|
34
34
|
Classifier: Programming Language :: Python
|
|
@@ -60,7 +60,7 @@ Add the following to your `.pre-commit-config.yaml` file to block commits with m
|
|
|
60
60
|
|
|
61
61
|
```yaml
|
|
62
62
|
- repo: https://github.com/stefmolin/docstringify
|
|
63
|
-
rev: 0.
|
|
63
|
+
rev: 0.3.0
|
|
64
64
|
hooks:
|
|
65
65
|
- id: docstringify
|
|
66
66
|
```
|
|
@@ -69,22 +69,34 @@ By default, all docstrings are required. If you want to be more lenient, you can
|
|
|
69
69
|
|
|
70
70
|
```yaml
|
|
71
71
|
- repo: https://github.com/stefmolin/docstringify
|
|
72
|
-
rev: 0.
|
|
72
|
+
rev: 0.3.0
|
|
73
73
|
hooks:
|
|
74
74
|
- id: docstringify
|
|
75
75
|
args: [--threshold=0.75]
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument.
|
|
78
|
+
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument, along with the docstring style you want to use (options are `google` and `numpydoc`). Here, we ask for [numpydoc-style docstring](https://numpydoc.readthedocs.io/en/latest/format.html#) suggestions:
|
|
79
79
|
|
|
80
80
|
```yaml
|
|
81
81
|
- repo: https://github.com/stefmolin/docstringify
|
|
82
|
-
rev: 0.
|
|
82
|
+
rev: 0.3.0
|
|
83
83
|
hooks:
|
|
84
84
|
- id: docstringify
|
|
85
|
-
args: [--suggest-changes]
|
|
85
|
+
args: [--suggest-changes=numpydoc]
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
Use `--make-changes` to create a copy of each file with docstring templates. Here, we ask for changes using the [Google docstring style](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html):
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- repo: https://github.com/stefmolin/docstringify
|
|
92
|
+
rev: 0.3.0
|
|
93
|
+
hooks:
|
|
94
|
+
- id: docstringify
|
|
95
|
+
args: [--make-changes=google]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If you want the changes to be made in place, change `--make-changes` to `--make-changes-inplace` – make sure you only operate on files that are in version control with this setting. Note that the resulting format of your file may be a little different (spacing, newlines, *etc.*).
|
|
99
|
+
|
|
88
100
|
Be sure to check out the [pre-commit documentation](https://pre-commit.com/#pre-commit-configyaml---hooks) for additional configuration options.
|
|
89
101
|
|
|
90
102
|
### Command line
|
|
@@ -124,10 +136,10 @@ test.say_hello is missing a docstring
|
|
|
124
136
|
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide a converter:
|
|
125
137
|
|
|
126
138
|
```pycon
|
|
127
|
-
>>> from docstringify.converters
|
|
139
|
+
>>> from docstringify.converters import NumpydocDocstringConverter
|
|
128
140
|
>>> from docstringify.visitor import DocstringVisitor
|
|
129
|
-
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter
|
|
130
|
-
>>> visitor.process_file()
|
|
141
|
+
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter)
|
|
142
|
+
>>> _ = visitor.process_file()
|
|
131
143
|
test is missing a docstring
|
|
132
144
|
Hint:
|
|
133
145
|
"""__description__"""
|
|
@@ -144,3 +156,17 @@ name : str, default="World"
|
|
|
144
156
|
"""
|
|
145
157
|
|
|
146
158
|
```
|
|
159
|
+
|
|
160
|
+
To make changes to your files, you will need to use the `DocstringTransformer` instead. With the `DocstringTransformer`, the converter is required:
|
|
161
|
+
|
|
162
|
+
```pycon
|
|
163
|
+
>>> from docstringify.converters import GoogleDocstringConverter
|
|
164
|
+
>>> from docstringify.transformer import DocstringTransformer
|
|
165
|
+
>>> transformer = DocstringTransformer('test.py', converter=GoogleDocstringConverter)
|
|
166
|
+
>>> _ = transformer.process_file()
|
|
167
|
+
test is missing a docstring
|
|
168
|
+
test.say_hello is missing a docstring
|
|
169
|
+
Docstring templates written to /.../test_docstringify.py
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
If you want to overwrite the file with the edits, pass `overwrite=True` to `DocstringTransformer()`.
|
|
@@ -9,7 +9,7 @@ Add the following to your `.pre-commit-config.yaml` file to block commits with m
|
|
|
9
9
|
|
|
10
10
|
```yaml
|
|
11
11
|
- repo: https://github.com/stefmolin/docstringify
|
|
12
|
-
rev: 0.
|
|
12
|
+
rev: 0.3.0
|
|
13
13
|
hooks:
|
|
14
14
|
- id: docstringify
|
|
15
15
|
```
|
|
@@ -18,22 +18,34 @@ By default, all docstrings are required. If you want to be more lenient, you can
|
|
|
18
18
|
|
|
19
19
|
```yaml
|
|
20
20
|
- repo: https://github.com/stefmolin/docstringify
|
|
21
|
-
rev: 0.
|
|
21
|
+
rev: 0.3.0
|
|
22
22
|
hooks:
|
|
23
23
|
- id: docstringify
|
|
24
24
|
args: [--threshold=0.75]
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument.
|
|
27
|
+
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument, along with the docstring style you want to use (options are `google` and `numpydoc`). Here, we ask for [numpydoc-style docstring](https://numpydoc.readthedocs.io/en/latest/format.html#) suggestions:
|
|
28
28
|
|
|
29
29
|
```yaml
|
|
30
30
|
- repo: https://github.com/stefmolin/docstringify
|
|
31
|
-
rev: 0.
|
|
31
|
+
rev: 0.3.0
|
|
32
32
|
hooks:
|
|
33
33
|
- id: docstringify
|
|
34
|
-
args: [--suggest-changes]
|
|
34
|
+
args: [--suggest-changes=numpydoc]
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
Use `--make-changes` to create a copy of each file with docstring templates. Here, we ask for changes using the [Google docstring style](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html):
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
- repo: https://github.com/stefmolin/docstringify
|
|
41
|
+
rev: 0.3.0
|
|
42
|
+
hooks:
|
|
43
|
+
- id: docstringify
|
|
44
|
+
args: [--make-changes=google]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If you want the changes to be made in place, change `--make-changes` to `--make-changes-inplace` – make sure you only operate on files that are in version control with this setting. Note that the resulting format of your file may be a little different (spacing, newlines, *etc.*).
|
|
48
|
+
|
|
37
49
|
Be sure to check out the [pre-commit documentation](https://pre-commit.com/#pre-commit-configyaml---hooks) for additional configuration options.
|
|
38
50
|
|
|
39
51
|
### Command line
|
|
@@ -73,10 +85,10 @@ test.say_hello is missing a docstring
|
|
|
73
85
|
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide a converter:
|
|
74
86
|
|
|
75
87
|
```pycon
|
|
76
|
-
>>> from docstringify.converters
|
|
88
|
+
>>> from docstringify.converters import NumpydocDocstringConverter
|
|
77
89
|
>>> from docstringify.visitor import DocstringVisitor
|
|
78
|
-
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter
|
|
79
|
-
>>> visitor.process_file()
|
|
90
|
+
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter)
|
|
91
|
+
>>> _ = visitor.process_file()
|
|
80
92
|
test is missing a docstring
|
|
81
93
|
Hint:
|
|
82
94
|
"""__description__"""
|
|
@@ -93,3 +105,17 @@ name : str, default="World"
|
|
|
93
105
|
"""
|
|
94
106
|
|
|
95
107
|
```
|
|
108
|
+
|
|
109
|
+
To make changes to your files, you will need to use the `DocstringTransformer` instead. With the `DocstringTransformer`, the converter is required:
|
|
110
|
+
|
|
111
|
+
```pycon
|
|
112
|
+
>>> from docstringify.converters import GoogleDocstringConverter
|
|
113
|
+
>>> from docstringify.transformer import DocstringTransformer
|
|
114
|
+
>>> transformer = DocstringTransformer('test.py', converter=GoogleDocstringConverter)
|
|
115
|
+
>>> _ = transformer.process_file()
|
|
116
|
+
test is missing a docstring
|
|
117
|
+
test.say_hello is missing a docstring
|
|
118
|
+
Docstring templates written to /.../test_docstringify.py
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If you want to overwrite the file with the edits, pass `overwrite=True` to `DocstringTransformer()`.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from functools import partial
|
|
6
|
+
from typing import Sequence
|
|
7
|
+
|
|
8
|
+
from . import __version__
|
|
9
|
+
from .converters import GoogleDocstringConverter, NumpydocDocstringConverter
|
|
10
|
+
from .transformer import DocstringTransformer
|
|
11
|
+
from .visitor import DocstringVisitor
|
|
12
|
+
|
|
13
|
+
PROG = __package__
|
|
14
|
+
|
|
15
|
+
STYLES = {
|
|
16
|
+
'google': GoogleDocstringConverter,
|
|
17
|
+
'numpydoc': NumpydocDocstringConverter,
|
|
18
|
+
}
|
|
19
|
+
CLI_DEFAULTS = {'threshold': 1.0}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
23
|
+
parser = argparse.ArgumentParser(prog=PROG)
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
'filenames',
|
|
26
|
+
nargs='*',
|
|
27
|
+
help='Filenames to process',
|
|
28
|
+
)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
'--version', action='version', version=f'%(prog)s {__version__}'
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
run_group = parser.add_argument_group('Run options')
|
|
34
|
+
handle_missing_docstring = run_group.add_mutually_exclusive_group(required=False)
|
|
35
|
+
handle_missing_docstring.add_argument(
|
|
36
|
+
'--make-changes',
|
|
37
|
+
choices=STYLES.keys(),
|
|
38
|
+
help='Whether to insert docstring templates for items missing docstrings',
|
|
39
|
+
)
|
|
40
|
+
handle_missing_docstring.add_argument(
|
|
41
|
+
'--make-changes-inplace',
|
|
42
|
+
choices=STYLES.keys(),
|
|
43
|
+
help=(
|
|
44
|
+
'Whether to insert docstring templates for items missing docstrings, '
|
|
45
|
+
'overwriting the original file'
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
handle_missing_docstring.add_argument(
|
|
49
|
+
'--suggest-changes',
|
|
50
|
+
choices=STYLES.keys(),
|
|
51
|
+
help='Whether to print out docstring templates for items missing docstrings',
|
|
52
|
+
)
|
|
53
|
+
run_group.add_argument(
|
|
54
|
+
'--threshold',
|
|
55
|
+
type=float,
|
|
56
|
+
default=CLI_DEFAULTS['threshold'],
|
|
57
|
+
help='The percentage of docstrings that must be present to pass',
|
|
58
|
+
)
|
|
59
|
+
args = parser.parse_args(argv)
|
|
60
|
+
|
|
61
|
+
if style := args.make_changes or args.make_changes_inplace or args.suggest_changes:
|
|
62
|
+
converter = STYLES[style]
|
|
63
|
+
else:
|
|
64
|
+
converter = None
|
|
65
|
+
|
|
66
|
+
get_docstring_processor = (
|
|
67
|
+
partial(
|
|
68
|
+
DocstringTransformer,
|
|
69
|
+
converter=converter,
|
|
70
|
+
**{'overwrite': bool(args.make_changes_inplace)},
|
|
71
|
+
)
|
|
72
|
+
if args.make_changes or args.make_changes_inplace
|
|
73
|
+
else partial(DocstringVisitor, converter=converter)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
docstrings_processed = missing_docstrings = 0
|
|
77
|
+
for file in args.filenames:
|
|
78
|
+
processor = get_docstring_processor(file)
|
|
79
|
+
processor.process_file()
|
|
80
|
+
missing_docstrings += processor.missing_docstrings
|
|
81
|
+
docstrings_processed += processor.docstrings_inspected
|
|
82
|
+
|
|
83
|
+
if docstrings_processed and (
|
|
84
|
+
missing_percentage := (missing_docstrings / docstrings_processed)
|
|
85
|
+
) > (1 - args.threshold):
|
|
86
|
+
print(f'\nMissing {missing_percentage:.0%} of docstrings', file=sys.stderr)
|
|
87
|
+
print(
|
|
88
|
+
f'Your settings require {args.threshold:.0%} of docstrings to be present',
|
|
89
|
+
file=sys.stderr,
|
|
90
|
+
)
|
|
91
|
+
return 1
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == '__main__':
|
|
96
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Docstring converters."""
|
|
2
|
+
|
|
3
|
+
from .base import DocstringConverter
|
|
4
|
+
from .google import GoogleDocstringConverter
|
|
5
|
+
from .numpydoc import NumpydocDocstringConverter
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
'DocstringConverter',
|
|
9
|
+
'GoogleDocstringConverter',
|
|
10
|
+
'NumpydocDocstringConverter',
|
|
11
|
+
]
|
|
@@ -2,26 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import textwrap
|
|
5
6
|
from abc import ABC, abstractmethod
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
9
|
+
from ..exceptions import InvalidDocstringError
|
|
10
|
+
|
|
8
11
|
if TYPE_CHECKING:
|
|
9
12
|
from ..components import Function, Parameter
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class DocstringConverter(ABC):
|
|
13
16
|
def __init__(
|
|
14
|
-
self,
|
|
17
|
+
self,
|
|
18
|
+
parameters_section_template: str,
|
|
19
|
+
returns_section_template: str,
|
|
20
|
+
quote: bool,
|
|
15
21
|
) -> None:
|
|
16
22
|
self.parameters_section_template = parameters_section_template
|
|
17
23
|
self.returns_section_template = returns_section_template
|
|
24
|
+
self._quote = quote
|
|
18
25
|
|
|
19
26
|
@abstractmethod
|
|
20
|
-
def to_class_docstring(self, class_name: str) -> str:
|
|
27
|
+
def to_class_docstring(self, class_name: str, indent: int) -> str:
|
|
21
28
|
pass
|
|
22
29
|
|
|
23
30
|
@abstractmethod
|
|
24
|
-
def to_function_docstring(self, function: Function) -> str:
|
|
31
|
+
def to_function_docstring(self, function: Function, indent: int) -> str:
|
|
25
32
|
pass
|
|
26
33
|
|
|
27
34
|
@abstractmethod
|
|
@@ -49,3 +56,18 @@ class DocstringConverter(ABC):
|
|
|
49
56
|
if return_text := self.format_return(return_type):
|
|
50
57
|
return self.returns_section_template.format(returns=return_text)
|
|
51
58
|
return ''
|
|
59
|
+
|
|
60
|
+
def quote_docstring(self, docstring: str | list[str], indent: int) -> str:
|
|
61
|
+
quote = '"""' if self._quote else ''
|
|
62
|
+
prefix = sep = ''
|
|
63
|
+
if isinstance(docstring, str):
|
|
64
|
+
docstring = [quote, docstring, quote]
|
|
65
|
+
elif isinstance(docstring, list):
|
|
66
|
+
if len(docstring) > 1:
|
|
67
|
+
prefix = ' ' * indent if indent else ''
|
|
68
|
+
sep = '\n'
|
|
69
|
+
docstring = [quote, *docstring, f'{prefix}{quote}']
|
|
70
|
+
else:
|
|
71
|
+
raise InvalidDocstringError(type(docstring).__name__)
|
|
72
|
+
|
|
73
|
+
return textwrap.indent(sep.join(docstring), prefix)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Google-style docstring converter."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..components import DESCRIPTION_PLACEHOLDER, NO_DEFAULT, Function, Parameter
|
|
6
|
+
from .base import DocstringConverter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GoogleDocstringConverter(DocstringConverter):
|
|
10
|
+
def __init__(self, quote: bool) -> None:
|
|
11
|
+
super().__init__(
|
|
12
|
+
parameters_section_template='Args:\n{parameters}',
|
|
13
|
+
returns_section_template='Returns:\n {returns}',
|
|
14
|
+
quote=quote,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
def to_function_docstring(self, function: Function, indent: int) -> str:
|
|
18
|
+
docstring = [DESCRIPTION_PLACEHOLDER]
|
|
19
|
+
|
|
20
|
+
if parameters_section := self.parameters_section(function.parameters):
|
|
21
|
+
docstring.extend(['', parameters_section])
|
|
22
|
+
|
|
23
|
+
if returns_section := self.returns_section(function.return_type):
|
|
24
|
+
docstring.extend(['', returns_section])
|
|
25
|
+
|
|
26
|
+
return self.quote_docstring(docstring, indent=indent)
|
|
27
|
+
|
|
28
|
+
def format_parameter(self, parameter: Parameter) -> str:
|
|
29
|
+
category = f'{f", {parameter.category}" if parameter.category else ""}'
|
|
30
|
+
return (
|
|
31
|
+
f' {parameter.name} ({parameter.type_}{category}): {DESCRIPTION_PLACEHOLDER}'
|
|
32
|
+
f'{f" Defaults to {parameter.default}." if parameter.default != NO_DEFAULT else ""}'
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def format_return(self, return_type: str | None) -> str:
|
|
36
|
+
if return_type:
|
|
37
|
+
return f'{return_type}: {DESCRIPTION_PLACEHOLDER}'
|
|
38
|
+
return ''
|
|
39
|
+
|
|
40
|
+
def to_module_docstring(self, module_name: str) -> str:
|
|
41
|
+
return self.quote_docstring(DESCRIPTION_PLACEHOLDER, indent=0)
|
|
42
|
+
|
|
43
|
+
def to_class_docstring(self, class_name: str, indent: int) -> str:
|
|
44
|
+
return self.quote_docstring(DESCRIPTION_PLACEHOLDER, indent=indent)
|
|
@@ -7,15 +7,15 @@ from .base import DocstringConverter
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class NumpydocDocstringConverter(DocstringConverter):
|
|
10
|
-
def __init__(self) -> None:
|
|
10
|
+
def __init__(self, quote: bool) -> None:
|
|
11
11
|
super().__init__(
|
|
12
12
|
parameters_section_template='Parameters\n----------\n{parameters}',
|
|
13
13
|
returns_section_template='Returns\n-------\n{returns}',
|
|
14
|
+
quote=quote,
|
|
14
15
|
)
|
|
15
16
|
|
|
16
|
-
def to_function_docstring(self, function: Function) -> str:
|
|
17
|
-
|
|
18
|
-
docstring = ['"""', DESCRIPTION_PLACEHOLDER]
|
|
17
|
+
def to_function_docstring(self, function: Function, indent: int) -> str:
|
|
18
|
+
docstring = [DESCRIPTION_PLACEHOLDER]
|
|
19
19
|
|
|
20
20
|
if parameters_section := self.parameters_section(function.parameters):
|
|
21
21
|
docstring.extend(['', parameters_section])
|
|
@@ -23,9 +23,7 @@ class NumpydocDocstringConverter(DocstringConverter):
|
|
|
23
23
|
if returns_section := self.returns_section(function.return_type):
|
|
24
24
|
docstring.extend(['', returns_section])
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return sep.join([*docstring, '"""'])
|
|
26
|
+
return self.quote_docstring(docstring, indent=indent)
|
|
29
27
|
|
|
30
28
|
def format_parameter(self, parameter: Parameter) -> str:
|
|
31
29
|
return (
|
|
@@ -41,7 +39,7 @@ class NumpydocDocstringConverter(DocstringConverter):
|
|
|
41
39
|
return ''
|
|
42
40
|
|
|
43
41
|
def to_module_docstring(self, module_name: str) -> str:
|
|
44
|
-
return
|
|
42
|
+
return self.quote_docstring(DESCRIPTION_PLACEHOLDER, indent=0)
|
|
45
43
|
|
|
46
|
-
def to_class_docstring(self, class_name: str) -> str:
|
|
47
|
-
return
|
|
44
|
+
def to_class_docstring(self, class_name: str, indent: int) -> str:
|
|
45
|
+
return self.quote_docstring(DESCRIPTION_PLACEHOLDER, indent=indent)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import ast
|
|
4
|
-
import sys
|
|
5
|
-
from pathlib import Path
|
|
6
4
|
from typing import TYPE_CHECKING, Literal
|
|
7
5
|
|
|
8
6
|
from .components import (
|
|
@@ -14,25 +12,20 @@ from .components import (
|
|
|
14
12
|
)
|
|
15
13
|
|
|
16
14
|
if TYPE_CHECKING:
|
|
17
|
-
from .converters
|
|
15
|
+
from .converters import DocstringConverter
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
class
|
|
18
|
+
class DocstringGenerator:
|
|
21
19
|
def __init__(
|
|
22
|
-
self,
|
|
20
|
+
self,
|
|
21
|
+
converter: type[DocstringConverter],
|
|
22
|
+
module_name: str,
|
|
23
|
+
source_code: str,
|
|
24
|
+
quote: bool,
|
|
23
25
|
) -> None:
|
|
24
|
-
self.
|
|
25
|
-
self.
|
|
26
|
-
|
|
27
|
-
self.docstrings_inspected: int = 0
|
|
28
|
-
self.missing_docstrings: int = 0
|
|
29
|
-
|
|
30
|
-
self.module_name: str = self.source_file.stem
|
|
31
|
-
self.stack: list[str] = []
|
|
32
|
-
|
|
33
|
-
self.provide_hints: bool = converter is not None
|
|
34
|
-
if self.provide_hints:
|
|
35
|
-
self.converter: DocstringVisitor = converter # TODO: consider whether this should be instantiated here instead of outside
|
|
26
|
+
self.converter = converter(quote=quote)
|
|
27
|
+
self.module_name = module_name
|
|
28
|
+
self.source_code = source_code
|
|
36
29
|
|
|
37
30
|
def _extract_default_values(
|
|
38
31
|
self, default: ast.Constant | None | Literal[NO_DEFAULT], is_keyword_only: bool
|
|
@@ -147,50 +140,18 @@ class DocstringVisitor(ast.NodeVisitor):
|
|
|
147
140
|
return RETURN_TYPE_PLACEHOLDER
|
|
148
141
|
return return_node
|
|
149
142
|
|
|
150
|
-
def report_missing_docstring(self) -> None:
|
|
151
|
-
self.missing_docstrings += 1
|
|
152
|
-
print(f'{".".join(self.stack)} is missing a docstring', file=sys.stderr)
|
|
153
|
-
|
|
154
143
|
def suggest_docstring(
|
|
155
|
-
self,
|
|
144
|
+
self,
|
|
145
|
+
node: ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module,
|
|
146
|
+
indent: int = 0,
|
|
156
147
|
) -> str:
|
|
157
148
|
if isinstance(node, ast.AsyncFunctionDef | ast.FunctionDef):
|
|
158
149
|
return self.converter.to_function_docstring(
|
|
159
|
-
Function(self.extract_arguments(node), self.extract_returns(node))
|
|
150
|
+
Function(self.extract_arguments(node), self.extract_returns(node)),
|
|
151
|
+
indent=indent,
|
|
160
152
|
)
|
|
161
153
|
|
|
162
154
|
if isinstance(node, ast.Module):
|
|
163
155
|
return self.converter.to_module_docstring(self.module_name)
|
|
164
156
|
|
|
165
|
-
|
|
166
|
-
# and suggest those parameters as the docstring for the class
|
|
167
|
-
# (may need to keep the class node in another stack)
|
|
168
|
-
return self.converter.to_class_docstring(node.name)
|
|
169
|
-
|
|
170
|
-
def process_docstring(
|
|
171
|
-
self, node: ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module
|
|
172
|
-
) -> None:
|
|
173
|
-
if not ast.get_docstring(node):
|
|
174
|
-
self.report_missing_docstring()
|
|
175
|
-
if self.provide_hints:
|
|
176
|
-
print('Hint:')
|
|
177
|
-
print(self.suggest_docstring(node))
|
|
178
|
-
print()
|
|
179
|
-
|
|
180
|
-
self.docstrings_inspected += 1
|
|
181
|
-
|
|
182
|
-
def visit(self, node: ast.AST) -> None:
|
|
183
|
-
if isinstance(
|
|
184
|
-
node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)
|
|
185
|
-
):
|
|
186
|
-
self.stack.append(
|
|
187
|
-
self.module_name if isinstance(node, ast.Module) else node.name
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
self.process_docstring(node)
|
|
191
|
-
|
|
192
|
-
self.generic_visit(node)
|
|
193
|
-
_ = self.stack.pop()
|
|
194
|
-
|
|
195
|
-
def process_file(self) -> None:
|
|
196
|
-
self.visit(ast.parse(self.source_code))
|
|
157
|
+
return self.converter.to_class_docstring(node.name, indent=indent)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from .visitor import DocstringVisitor
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from .converters import DocstringConverter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DocstringTransformer(ast.NodeTransformer, DocstringVisitor):
|
|
13
|
+
def __init__(
|
|
14
|
+
self, filename: str, converter: DocstringConverter, overwrite: bool = False
|
|
15
|
+
) -> None:
|
|
16
|
+
super().__init__(filename, converter)
|
|
17
|
+
self.overwrite = overwrite
|
|
18
|
+
|
|
19
|
+
def save(self, new_ast: ast.Module) -> None:
|
|
20
|
+
if self.missing_docstrings:
|
|
21
|
+
output = (
|
|
22
|
+
self.source_file
|
|
23
|
+
if self.overwrite
|
|
24
|
+
else self.source_file.parent
|
|
25
|
+
/ (
|
|
26
|
+
self.source_file.stem
|
|
27
|
+
+ '_docstringify'
|
|
28
|
+
+ ''.join(self.source_file.suffixes)
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
edited_code = ast.unparse(new_ast)
|
|
32
|
+
output.write_text(edited_code)
|
|
33
|
+
print(f'Docstring templates written to {output}')
|
|
34
|
+
else:
|
|
35
|
+
print(
|
|
36
|
+
f'No missing docstrings found in {self.source_file}; no changes made.'
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def handle_missing_docstring(
|
|
40
|
+
self, node: ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module
|
|
41
|
+
) -> ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module:
|
|
42
|
+
suggested_docstring = self.docstring_generator.suggest_docstring(
|
|
43
|
+
node, indent=0 if isinstance(node, ast.Module) else node.col_offset + 4
|
|
44
|
+
)
|
|
45
|
+
docstring = ast.Expr(ast.Constant(suggested_docstring))
|
|
46
|
+
node.body.insert(0, docstring)
|
|
47
|
+
return ast.fix_missing_locations(node)
|
|
48
|
+
|
|
49
|
+
def process_file(self) -> ast.Module:
|
|
50
|
+
root = ast.parse(self.source_code)
|
|
51
|
+
new_ast = self.visit(root)
|
|
52
|
+
self.save(new_ast)
|
|
53
|
+
return new_ast
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from .docstring_generator import DocstringGenerator
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .converters import DocstringConverter
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DocstringVisitor(ast.NodeVisitor):
|
|
15
|
+
def __init__(
|
|
16
|
+
self, filename: str, converter: DocstringConverter | None = None
|
|
17
|
+
) -> None:
|
|
18
|
+
self.source_file: Path = Path(filename).expanduser().resolve()
|
|
19
|
+
self.source_code: str = self.source_file.read_text()
|
|
20
|
+
|
|
21
|
+
self.docstrings_inspected: int = 0
|
|
22
|
+
self.missing_docstrings: int = 0
|
|
23
|
+
|
|
24
|
+
self.module_name: str = self.source_file.stem
|
|
25
|
+
self.stack: list[str] = []
|
|
26
|
+
|
|
27
|
+
self.provide_hints: bool = converter is not None
|
|
28
|
+
if self.provide_hints:
|
|
29
|
+
self.docstring_generator = DocstringGenerator(
|
|
30
|
+
converter,
|
|
31
|
+
self.module_name,
|
|
32
|
+
self.source_code,
|
|
33
|
+
quote=not issubclass(self.__class__, ast.NodeTransformer),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def report_missing_docstring(self) -> None:
|
|
37
|
+
self.missing_docstrings += 1
|
|
38
|
+
print(f'{".".join(self.stack)} is missing a docstring', file=sys.stderr)
|
|
39
|
+
|
|
40
|
+
def handle_missing_docstring(
|
|
41
|
+
self, node: ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module
|
|
42
|
+
) -> ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module:
|
|
43
|
+
if self.provide_hints:
|
|
44
|
+
print('Hint:')
|
|
45
|
+
print(self.docstring_generator.suggest_docstring(node))
|
|
46
|
+
print()
|
|
47
|
+
return node
|
|
48
|
+
|
|
49
|
+
def process_docstring(
|
|
50
|
+
self, node: ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module
|
|
51
|
+
) -> ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.Module:
|
|
52
|
+
if not ast.get_docstring(node):
|
|
53
|
+
self.report_missing_docstring()
|
|
54
|
+
node = self.handle_missing_docstring(node)
|
|
55
|
+
|
|
56
|
+
self.docstrings_inspected += 1
|
|
57
|
+
return node
|
|
58
|
+
|
|
59
|
+
def visit(self, node: ast.AST) -> ast.AST:
|
|
60
|
+
if isinstance(
|
|
61
|
+
node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)
|
|
62
|
+
):
|
|
63
|
+
self.stack.append(
|
|
64
|
+
self.module_name if isinstance(node, ast.Module) else node.name
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
node = self.process_docstring(node)
|
|
68
|
+
|
|
69
|
+
self.generic_visit(node)
|
|
70
|
+
_ = self.stack.pop()
|
|
71
|
+
return node
|
|
72
|
+
|
|
73
|
+
def process_file(self) -> ast.Module:
|
|
74
|
+
root = self.visit(ast.parse(self.source_code))
|
|
75
|
+
|
|
76
|
+
if not self.missing_docstrings:
|
|
77
|
+
print(f'No missing docstrings found in {self.source_file}.')
|
|
78
|
+
|
|
79
|
+
return root
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docstringify
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Flag missing docstrings and, optionally, generate them from signatures and type annotations.
|
|
5
5
|
Author-email: Stefanie Molin <docstringify@stefaniemolin.com>
|
|
6
6
|
License: MIT License
|
|
@@ -28,7 +28,7 @@ License: MIT License
|
|
|
28
28
|
Project-URL: Documentation, https://github.com/stefmolin/docstringify
|
|
29
29
|
Project-URL: Homepage, https://github.com/stefmolin/docstringify
|
|
30
30
|
Project-URL: Source, https://github.com/stefmolin/docstringify
|
|
31
|
-
Keywords: ast,docstring generation,numpydoc-style docstring,pre-commit
|
|
31
|
+
Keywords: ast,docstring generation,google-style docstring,numpydoc-style docstring,pre-commit
|
|
32
32
|
Classifier: Development Status :: 3 - Alpha
|
|
33
33
|
Classifier: License :: OSI Approved :: MIT License
|
|
34
34
|
Classifier: Programming Language :: Python
|
|
@@ -60,7 +60,7 @@ Add the following to your `.pre-commit-config.yaml` file to block commits with m
|
|
|
60
60
|
|
|
61
61
|
```yaml
|
|
62
62
|
- repo: https://github.com/stefmolin/docstringify
|
|
63
|
-
rev: 0.
|
|
63
|
+
rev: 0.3.0
|
|
64
64
|
hooks:
|
|
65
65
|
- id: docstringify
|
|
66
66
|
```
|
|
@@ -69,22 +69,34 @@ By default, all docstrings are required. If you want to be more lenient, you can
|
|
|
69
69
|
|
|
70
70
|
```yaml
|
|
71
71
|
- repo: https://github.com/stefmolin/docstringify
|
|
72
|
-
rev: 0.
|
|
72
|
+
rev: 0.3.0
|
|
73
73
|
hooks:
|
|
74
74
|
- id: docstringify
|
|
75
75
|
args: [--threshold=0.75]
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument.
|
|
78
|
+
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide the `--suggest-changes` argument, along with the docstring style you want to use (options are `google` and `numpydoc`). Here, we ask for [numpydoc-style docstring](https://numpydoc.readthedocs.io/en/latest/format.html#) suggestions:
|
|
79
79
|
|
|
80
80
|
```yaml
|
|
81
81
|
- repo: https://github.com/stefmolin/docstringify
|
|
82
|
-
rev: 0.
|
|
82
|
+
rev: 0.3.0
|
|
83
83
|
hooks:
|
|
84
84
|
- id: docstringify
|
|
85
|
-
args: [--suggest-changes]
|
|
85
|
+
args: [--suggest-changes=numpydoc]
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
Use `--make-changes` to create a copy of each file with docstring templates. Here, we ask for changes using the [Google docstring style](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html):
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- repo: https://github.com/stefmolin/docstringify
|
|
92
|
+
rev: 0.3.0
|
|
93
|
+
hooks:
|
|
94
|
+
- id: docstringify
|
|
95
|
+
args: [--make-changes=google]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If you want the changes to be made in place, change `--make-changes` to `--make-changes-inplace` – make sure you only operate on files that are in version control with this setting. Note that the resulting format of your file may be a little different (spacing, newlines, *etc.*).
|
|
99
|
+
|
|
88
100
|
Be sure to check out the [pre-commit documentation](https://pre-commit.com/#pre-commit-configyaml---hooks) for additional configuration options.
|
|
89
101
|
|
|
90
102
|
### Command line
|
|
@@ -124,10 +136,10 @@ test.say_hello is missing a docstring
|
|
|
124
136
|
If you would like to see suggested docstring templates (inferred from type annotations for functions and methods), provide a converter:
|
|
125
137
|
|
|
126
138
|
```pycon
|
|
127
|
-
>>> from docstringify.converters
|
|
139
|
+
>>> from docstringify.converters import NumpydocDocstringConverter
|
|
128
140
|
>>> from docstringify.visitor import DocstringVisitor
|
|
129
|
-
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter
|
|
130
|
-
>>> visitor.process_file()
|
|
141
|
+
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter)
|
|
142
|
+
>>> _ = visitor.process_file()
|
|
131
143
|
test is missing a docstring
|
|
132
144
|
Hint:
|
|
133
145
|
"""__description__"""
|
|
@@ -144,3 +156,17 @@ name : str, default="World"
|
|
|
144
156
|
"""
|
|
145
157
|
|
|
146
158
|
```
|
|
159
|
+
|
|
160
|
+
To make changes to your files, you will need to use the `DocstringTransformer` instead. With the `DocstringTransformer`, the converter is required:
|
|
161
|
+
|
|
162
|
+
```pycon
|
|
163
|
+
>>> from docstringify.converters import GoogleDocstringConverter
|
|
164
|
+
>>> from docstringify.transformer import DocstringTransformer
|
|
165
|
+
>>> transformer = DocstringTransformer('test.py', converter=GoogleDocstringConverter)
|
|
166
|
+
>>> _ = transformer.process_file()
|
|
167
|
+
test is missing a docstring
|
|
168
|
+
test.say_hello is missing a docstring
|
|
169
|
+
Docstring templates written to /.../test_docstringify.py
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
If you want to overwrite the file with the edits, pass `overwrite=True` to `DocstringTransformer()`.
|
|
@@ -12,6 +12,9 @@ src/docstringify/__init__.py
|
|
|
12
12
|
src/docstringify/__main__.py
|
|
13
13
|
src/docstringify/cli.py
|
|
14
14
|
src/docstringify/components.py
|
|
15
|
+
src/docstringify/docstring_generator.py
|
|
16
|
+
src/docstringify/exceptions.py
|
|
17
|
+
src/docstringify/transformer.py
|
|
15
18
|
src/docstringify/visitor.py
|
|
16
19
|
src/docstringify.egg-info/PKG-INFO
|
|
17
20
|
src/docstringify.egg-info/SOURCES.txt
|
|
@@ -21,4 +24,5 @@ src/docstringify.egg-info/requires.txt
|
|
|
21
24
|
src/docstringify.egg-info/top_level.txt
|
|
22
25
|
src/docstringify/converters/__init__.py
|
|
23
26
|
src/docstringify/converters/base.py
|
|
27
|
+
src/docstringify/converters/google.py
|
|
24
28
|
src/docstringify/converters/numpydoc.py
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import sys
|
|
5
|
-
from typing import Sequence
|
|
6
|
-
|
|
7
|
-
from . import __version__
|
|
8
|
-
from .converters.numpydoc import NumpydocDocstringConverter
|
|
9
|
-
from .visitor import DocstringVisitor
|
|
10
|
-
|
|
11
|
-
PROG = __package__
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def main(argv: Sequence[str] | None = None) -> int:
|
|
15
|
-
parser = argparse.ArgumentParser(prog=PROG)
|
|
16
|
-
parser.add_argument(
|
|
17
|
-
'filenames',
|
|
18
|
-
nargs='*',
|
|
19
|
-
help='Filenames to process',
|
|
20
|
-
)
|
|
21
|
-
parser.add_argument(
|
|
22
|
-
'--version', action='version', version=f'%(prog)s {__version__}'
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
parser.add_argument(
|
|
26
|
-
'--suggest-changes',
|
|
27
|
-
action='store_true',
|
|
28
|
-
help='Whether to provide docstring templates for items missing docstrings',
|
|
29
|
-
)
|
|
30
|
-
parser.add_argument(
|
|
31
|
-
'--style',
|
|
32
|
-
choices=['numpydoc'],
|
|
33
|
-
default='numpydoc',
|
|
34
|
-
help='The style of docstring to use (only used when --suggest-changes is passed)',
|
|
35
|
-
)
|
|
36
|
-
parser.add_argument(
|
|
37
|
-
'--threshold',
|
|
38
|
-
type=float,
|
|
39
|
-
default=1,
|
|
40
|
-
help='The percentage of docstrings that must be present to pass',
|
|
41
|
-
)
|
|
42
|
-
args = parser.parse_args(argv)
|
|
43
|
-
|
|
44
|
-
if args.style is None or not args.suggest_changes:
|
|
45
|
-
converter = None
|
|
46
|
-
elif args.style == 'numpydoc':
|
|
47
|
-
converter = NumpydocDocstringConverter()
|
|
48
|
-
else:
|
|
49
|
-
raise NotImplementedError(f'{args.style} is not a supported option')
|
|
50
|
-
|
|
51
|
-
docstrings_processed = missing_docstrings = 0
|
|
52
|
-
for file in args.filenames:
|
|
53
|
-
visitor = DocstringVisitor(file, converter=converter)
|
|
54
|
-
visitor.process_file()
|
|
55
|
-
missing_docstrings += visitor.missing_docstrings
|
|
56
|
-
docstrings_processed += visitor.docstrings_inspected
|
|
57
|
-
|
|
58
|
-
if docstrings_processed and (
|
|
59
|
-
missing_percentage := (missing_docstrings / docstrings_processed)
|
|
60
|
-
) > (1 - args.threshold):
|
|
61
|
-
print(f'Missing {missing_percentage:.0%} of docstrings', file=sys.stderr)
|
|
62
|
-
print(
|
|
63
|
-
f'Your settings require {args.threshold:.0%} of docstrings to be present',
|
|
64
|
-
file=sys.stderr,
|
|
65
|
-
)
|
|
66
|
-
return 1
|
|
67
|
-
return 0
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if __name__ == '__main__':
|
|
71
|
-
raise SystemExit(main())
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Docstring converters."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|