docstringify 0.2.0__tar.gz → 0.4.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.4.0/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- docstringify-0.4.0/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- docstringify-0.4.0/.github/workflows/greetings.yml +16 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/PKG-INFO +28 -12
- {docstringify-0.2.0 → docstringify-0.4.0}/README.md +27 -11
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/__init__.py +1 -1
- docstringify-0.4.0/src/docstringify/cli.py +95 -0
- docstringify-0.4.0/src/docstringify/converters/base.py +94 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/converters/google.py +9 -11
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/converters/numpydoc.py +8 -10
- docstringify-0.4.0/src/docstringify/exceptions.py +6 -0
- docstringify-0.4.0/src/docstringify/nodes/__init__.py +1 -0
- docstringify-0.4.0/src/docstringify/nodes/base.py +53 -0
- docstringify-0.4.0/src/docstringify/nodes/function.py +159 -0
- docstringify-0.4.0/src/docstringify/traversal/__init__.py +9 -0
- docstringify-0.4.0/src/docstringify/traversal/transformer.py +64 -0
- docstringify-0.4.0/src/docstringify/traversal/visitor.py +100 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/PKG-INFO +28 -12
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/SOURCES.txt +11 -2
- docstringify-0.2.0/src/docstringify/cli.py +0 -73
- docstringify-0.2.0/src/docstringify/converters/base.py +0 -51
- docstringify-0.2.0/src/docstringify/visitor.py +0 -196
- {docstringify-0.2.0 → docstringify-0.4.0}/.github/dependabot.yml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.github/release.yml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.github/workflows/ci.yml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.github/workflows/pypi-publish.yml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.gitignore +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.pre-commit-config.yaml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/.pre-commit-hooks.yaml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/LICENSE +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/pyproject.toml +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/setup.cfg +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/__main__.py +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/components.py +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify/converters/__init__.py +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/dependency_links.txt +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/entry_points.txt +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/requires.txt +0 -0
- {docstringify-0.2.0 → docstringify-0.4.0}/src/docstringify.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something isn't working
|
|
4
|
+
title: "[BUG] "
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Required attestation**
|
|
11
|
+
- [ ] I have checked that this issue has not already been reported.
|
|
12
|
+
- [ ] I have confirmed this bug exists on the latest version of docstringify.
|
|
13
|
+
- [ ] I have confirmed this bug exists on the `main` branch of docstringify.
|
|
14
|
+
|
|
15
|
+
**Describe the bug**
|
|
16
|
+
A clear and concise description of what the bug is.
|
|
17
|
+
|
|
18
|
+
**To Reproduce**
|
|
19
|
+
Steps to reproduce the behavior.
|
|
20
|
+
|
|
21
|
+
**Expected behavior**
|
|
22
|
+
A clear and concise description of what you expected to happen.
|
|
23
|
+
|
|
24
|
+
**Screenshots**
|
|
25
|
+
If applicable, add screenshots to help explain your problem.
|
|
26
|
+
|
|
27
|
+
**Environment**
|
|
28
|
+
- OS: [e.g. iOS]
|
|
29
|
+
- Python Version [e.g. 3.12]
|
|
30
|
+
|
|
31
|
+
**Additional context**
|
|
32
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Is your feature request related to a problem? Please describe.**
|
|
11
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
12
|
+
|
|
13
|
+
**Describe the solution you'd like**
|
|
14
|
+
A clear and concise description of what you want to happen.
|
|
15
|
+
|
|
16
|
+
**Describe alternatives you've considered**
|
|
17
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
18
|
+
|
|
19
|
+
**Additional context**
|
|
20
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Greetings
|
|
2
|
+
|
|
3
|
+
on: [pull_request_target, issues]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
greeting:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
permissions:
|
|
9
|
+
issues: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/first-interaction@34f15e814fe48ac9312ccf29db4e74fa767cbab7 # v1.3.0
|
|
13
|
+
with:
|
|
14
|
+
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
15
|
+
issue-message: "It looks like this is your first issue here – welcome! Please familiarize yourself with the [contributing guidelines](https://github.com/stefmolin/docstringify/blob/main/CONTRIBUTING.md), if you haven't already."
|
|
16
|
+
pr-message: "Congratulations on making your first pull request to `docstringify`! Please familiarize yourself with the [contributing guidelines](https://github.com/stefmolin/docstringify/blob/main/CONTRIBUTING.md), if you haven't already."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docstringify
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.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
|
|
@@ -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.4.0
|
|
64
64
|
hooks:
|
|
65
65
|
- id: docstringify
|
|
66
66
|
```
|
|
@@ -69,32 +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.4.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.4.0
|
|
83
83
|
hooks:
|
|
84
84
|
- id: docstringify
|
|
85
|
-
args: [--suggest-changes]
|
|
85
|
+
args: [--suggest-changes=numpydoc]
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
|
|
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
89
|
|
|
90
90
|
```yaml
|
|
91
91
|
- repo: https://github.com/stefmolin/docstringify
|
|
92
|
-
rev: 0.
|
|
92
|
+
rev: 0.4.0
|
|
93
93
|
hooks:
|
|
94
94
|
- id: docstringify
|
|
95
|
-
args: [--
|
|
95
|
+
args: [--make-changes=google]
|
|
96
96
|
```
|
|
97
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
|
+
|
|
98
100
|
Be sure to check out the [pre-commit documentation](https://pre-commit.com/#pre-commit-configyaml---hooks) for additional configuration options.
|
|
99
101
|
|
|
100
102
|
### Command line
|
|
@@ -124,7 +126,7 @@ $ python -m pip install docstringify
|
|
|
124
126
|
Then, use the `DocstringVisitor()` class on individual files to see spots where docstrings are missing:
|
|
125
127
|
|
|
126
128
|
```pycon
|
|
127
|
-
>>> from docstringify.
|
|
129
|
+
>>> from docstringify.traversal import DocstringVisitor
|
|
128
130
|
>>> visitor = DocstringVisitor('test.py')
|
|
129
131
|
>>> visitor.process_file()
|
|
130
132
|
test is missing a docstring
|
|
@@ -135,8 +137,8 @@ If you would like to see suggested docstring templates (inferred from type annot
|
|
|
135
137
|
|
|
136
138
|
```pycon
|
|
137
139
|
>>> from docstringify.converters import NumpydocDocstringConverter
|
|
138
|
-
>>> from docstringify.
|
|
139
|
-
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter
|
|
140
|
+
>>> from docstringify.traversal import DocstringVisitor
|
|
141
|
+
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter)
|
|
140
142
|
>>> visitor.process_file()
|
|
141
143
|
test is missing a docstring
|
|
142
144
|
Hint:
|
|
@@ -154,3 +156,17 @@ name : str, default="World"
|
|
|
154
156
|
"""
|
|
155
157
|
|
|
156
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.traversal 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.4.0
|
|
13
13
|
hooks:
|
|
14
14
|
- id: docstringify
|
|
15
15
|
```
|
|
@@ -18,32 +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.4.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.4.0
|
|
32
32
|
hooks:
|
|
33
33
|
- id: docstringify
|
|
34
|
-
args: [--suggest-changes]
|
|
34
|
+
args: [--suggest-changes=numpydoc]
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
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
38
|
|
|
39
39
|
```yaml
|
|
40
40
|
- repo: https://github.com/stefmolin/docstringify
|
|
41
|
-
rev: 0.
|
|
41
|
+
rev: 0.4.0
|
|
42
42
|
hooks:
|
|
43
43
|
- id: docstringify
|
|
44
|
-
args: [--
|
|
44
|
+
args: [--make-changes=google]
|
|
45
45
|
```
|
|
46
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
|
+
|
|
47
49
|
Be sure to check out the [pre-commit documentation](https://pre-commit.com/#pre-commit-configyaml---hooks) for additional configuration options.
|
|
48
50
|
|
|
49
51
|
### Command line
|
|
@@ -73,7 +75,7 @@ $ python -m pip install docstringify
|
|
|
73
75
|
Then, use the `DocstringVisitor()` class on individual files to see spots where docstrings are missing:
|
|
74
76
|
|
|
75
77
|
```pycon
|
|
76
|
-
>>> from docstringify.
|
|
78
|
+
>>> from docstringify.traversal import DocstringVisitor
|
|
77
79
|
>>> visitor = DocstringVisitor('test.py')
|
|
78
80
|
>>> visitor.process_file()
|
|
79
81
|
test is missing a docstring
|
|
@@ -84,8 +86,8 @@ If you would like to see suggested docstring templates (inferred from type annot
|
|
|
84
86
|
|
|
85
87
|
```pycon
|
|
86
88
|
>>> from docstringify.converters import NumpydocDocstringConverter
|
|
87
|
-
>>> from docstringify.
|
|
88
|
-
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter
|
|
89
|
+
>>> from docstringify.traversal import DocstringVisitor
|
|
90
|
+
>>> visitor = DocstringVisitor('test.py', converter=NumpydocDocstringConverter)
|
|
89
91
|
>>> visitor.process_file()
|
|
90
92
|
test is missing a docstring
|
|
91
93
|
Hint:
|
|
@@ -103,3 +105,17 @@ name : str, default="World"
|
|
|
103
105
|
"""
|
|
104
106
|
|
|
105
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.traversal 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,95 @@
|
|
|
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 .traversal import DocstringTransformer, DocstringVisitor
|
|
11
|
+
|
|
12
|
+
PROG = __package__
|
|
13
|
+
|
|
14
|
+
STYLES = {
|
|
15
|
+
'google': GoogleDocstringConverter,
|
|
16
|
+
'numpydoc': NumpydocDocstringConverter,
|
|
17
|
+
}
|
|
18
|
+
CLI_DEFAULTS = {'threshold': 1.0}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
22
|
+
parser = argparse.ArgumentParser(prog=PROG)
|
|
23
|
+
parser.add_argument(
|
|
24
|
+
'filenames',
|
|
25
|
+
nargs='*',
|
|
26
|
+
help='Filenames to process',
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
'--version', action='version', version=f'%(prog)s {__version__}'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
run_group = parser.add_argument_group('Run options')
|
|
33
|
+
handle_missing_docstring = run_group.add_mutually_exclusive_group(required=False)
|
|
34
|
+
handle_missing_docstring.add_argument(
|
|
35
|
+
'--make-changes',
|
|
36
|
+
choices=STYLES.keys(),
|
|
37
|
+
help='Whether to insert docstring templates for items missing docstrings',
|
|
38
|
+
)
|
|
39
|
+
handle_missing_docstring.add_argument(
|
|
40
|
+
'--make-changes-inplace',
|
|
41
|
+
choices=STYLES.keys(),
|
|
42
|
+
help=(
|
|
43
|
+
'Whether to insert docstring templates for items missing docstrings, '
|
|
44
|
+
'overwriting the original file'
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
handle_missing_docstring.add_argument(
|
|
48
|
+
'--suggest-changes',
|
|
49
|
+
choices=STYLES.keys(),
|
|
50
|
+
help='Whether to print out docstring templates for items missing docstrings',
|
|
51
|
+
)
|
|
52
|
+
run_group.add_argument(
|
|
53
|
+
'--threshold',
|
|
54
|
+
type=float,
|
|
55
|
+
default=CLI_DEFAULTS['threshold'],
|
|
56
|
+
help='The percentage of docstrings that must be present to pass',
|
|
57
|
+
)
|
|
58
|
+
args = parser.parse_args(argv)
|
|
59
|
+
|
|
60
|
+
if style := args.make_changes or args.make_changes_inplace or args.suggest_changes:
|
|
61
|
+
converter = STYLES[style]
|
|
62
|
+
else:
|
|
63
|
+
converter = None
|
|
64
|
+
|
|
65
|
+
get_docstring_processor = (
|
|
66
|
+
partial(
|
|
67
|
+
DocstringTransformer,
|
|
68
|
+
converter=converter,
|
|
69
|
+
**{'overwrite': bool(args.make_changes_inplace)},
|
|
70
|
+
)
|
|
71
|
+
if args.make_changes or args.make_changes_inplace
|
|
72
|
+
else partial(DocstringVisitor, converter=converter)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
docstrings_processed = missing_docstrings = 0
|
|
76
|
+
for file in args.filenames:
|
|
77
|
+
processor = get_docstring_processor(file)
|
|
78
|
+
processor.process_file()
|
|
79
|
+
missing_docstrings += processor.missing_docstrings
|
|
80
|
+
docstrings_processed += processor.docstrings_inspected
|
|
81
|
+
|
|
82
|
+
if docstrings_processed and (
|
|
83
|
+
missing_percentage := (missing_docstrings / docstrings_processed)
|
|
84
|
+
) > (1 - args.threshold):
|
|
85
|
+
print(f'Missing {missing_percentage:.0%} of docstrings', file=sys.stderr)
|
|
86
|
+
print(
|
|
87
|
+
f'Your settings require {args.threshold:.0%} of docstrings to be present',
|
|
88
|
+
file=sys.stderr,
|
|
89
|
+
)
|
|
90
|
+
return 1
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == '__main__':
|
|
95
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Base docstring converter."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
import textwrap
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from ..components import Function
|
|
11
|
+
from ..exceptions import InvalidDocstringError
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from ..components import Parameter
|
|
15
|
+
from ..nodes.base import DocstringNode
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DocstringConverter(ABC):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
parameters_section_template: str,
|
|
22
|
+
returns_section_template: str,
|
|
23
|
+
quote: bool,
|
|
24
|
+
) -> None:
|
|
25
|
+
self.parameters_section_template = parameters_section_template
|
|
26
|
+
self.returns_section_template = returns_section_template
|
|
27
|
+
self._quote = quote
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def to_class_docstring(self, class_name: str, indent: int) -> str:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def to_function_docstring(self, function: Function, indent: int) -> str:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def to_module_docstring(self, module_name: str) -> str:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def format_parameter(self, parameter: Parameter) -> str:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
def parameters_section(self, parameters: tuple[Parameter, ...]) -> str:
|
|
46
|
+
if parameters:
|
|
47
|
+
return self.parameters_section_template.format(
|
|
48
|
+
parameters='\n'.join(
|
|
49
|
+
self.format_parameter(parameter) for parameter in parameters
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
return ''
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def format_return(self, return_type: str | None) -> str:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def returns_section(self, return_type: str | None) -> str:
|
|
59
|
+
if return_text := self.format_return(return_type):
|
|
60
|
+
return self.returns_section_template.format(returns=return_text)
|
|
61
|
+
return ''
|
|
62
|
+
|
|
63
|
+
def quote_docstring(self, docstring: str | list[str], indent: int) -> str:
|
|
64
|
+
quote = '"""' if self._quote else ''
|
|
65
|
+
prefix = sep = ''
|
|
66
|
+
if isinstance(docstring, str):
|
|
67
|
+
docstring = [quote, docstring, quote]
|
|
68
|
+
elif isinstance(docstring, list):
|
|
69
|
+
if len(docstring) > 1:
|
|
70
|
+
prefix = ' ' * indent if indent else ''
|
|
71
|
+
sep = '\n'
|
|
72
|
+
docstring = [quote, *docstring, f'{prefix}{quote}']
|
|
73
|
+
else:
|
|
74
|
+
raise InvalidDocstringError(type(docstring).__name__)
|
|
75
|
+
|
|
76
|
+
return textwrap.indent(sep.join(docstring), prefix)
|
|
77
|
+
|
|
78
|
+
def suggest_docstring(
|
|
79
|
+
self,
|
|
80
|
+
docstring_node: DocstringNode,
|
|
81
|
+
indent: int = 0,
|
|
82
|
+
) -> str:
|
|
83
|
+
if isinstance(docstring_node.ast_node, ast.AsyncFunctionDef | ast.FunctionDef):
|
|
84
|
+
return self.to_function_docstring(
|
|
85
|
+
Function(
|
|
86
|
+
docstring_node.extract_arguments(), docstring_node.extract_returns()
|
|
87
|
+
),
|
|
88
|
+
indent=indent,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if isinstance(docstring_node.ast_node, ast.Module):
|
|
92
|
+
return self.to_module_docstring(docstring_node.module_name)
|
|
93
|
+
|
|
94
|
+
return self.to_class_docstring(docstring_node.name, indent=indent)
|
|
@@ -7,15 +7,15 @@ from .base import DocstringConverter
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class GoogleDocstringConverter(DocstringConverter):
|
|
10
|
-
def __init__(self) -> None:
|
|
10
|
+
def __init__(self, quote: bool) -> None:
|
|
11
11
|
super().__init__(
|
|
12
12
|
parameters_section_template='Args:\n{parameters}',
|
|
13
13
|
returns_section_template='Returns:\n {returns}',
|
|
14
|
+
quote=quote,
|
|
14
15
|
)
|
|
15
16
|
|
|
16
|
-
def to_function_docstring(self, function: Function) -> str:
|
|
17
|
-
|
|
18
|
-
docstring = [f'"""{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,14 +23,12 @@ class GoogleDocstringConverter(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
|
category = f'{f", {parameter.category}" if parameter.category else ""}'
|
|
32
30
|
return (
|
|
33
|
-
f' {parameter.name} ({parameter.type_}{category}): {DESCRIPTION_PLACEHOLDER}
|
|
31
|
+
f' {parameter.name} ({parameter.type_}{category}): {DESCRIPTION_PLACEHOLDER}'
|
|
34
32
|
f'{f" Defaults to {parameter.default}." if parameter.default != NO_DEFAULT else ""}'
|
|
35
33
|
)
|
|
36
34
|
|
|
@@ -40,7 +38,7 @@ class GoogleDocstringConverter(DocstringConverter):
|
|
|
40
38
|
return ''
|
|
41
39
|
|
|
42
40
|
def to_module_docstring(self, module_name: str) -> str:
|
|
43
|
-
return
|
|
41
|
+
return self.quote_docstring(DESCRIPTION_PLACEHOLDER, indent=0)
|
|
44
42
|
|
|
45
|
-
def to_class_docstring(self, class_name: str) -> str:
|
|
46
|
-
return
|
|
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)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Docstringify nodes."""
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
from functools import partial
|
|
5
|
+
from typing import Callable, overload
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DocstringNode:
|
|
9
|
+
@overload
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
node: ast.Module,
|
|
13
|
+
module_name: str,
|
|
14
|
+
source_code: str,
|
|
15
|
+
parent: None = None,
|
|
16
|
+
) -> None: ...
|
|
17
|
+
|
|
18
|
+
@overload
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
node: ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef,
|
|
22
|
+
module_name: str,
|
|
23
|
+
source_code: str,
|
|
24
|
+
parent: DocstringNode,
|
|
25
|
+
) -> None: ...
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
node: ast.Module | ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef,
|
|
30
|
+
module_name: str,
|
|
31
|
+
source_code: str,
|
|
32
|
+
parent: DocstringNode | None = None,
|
|
33
|
+
) -> None:
|
|
34
|
+
self.module_name: str = module_name
|
|
35
|
+
self.parent: DocstringNode | None = parent
|
|
36
|
+
|
|
37
|
+
self.ast_node: (
|
|
38
|
+
ast.Module | ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef
|
|
39
|
+
) = node
|
|
40
|
+
self.name: str = getattr(node, 'name', self.module_name)
|
|
41
|
+
|
|
42
|
+
self.docstring = ast.get_docstring(node)
|
|
43
|
+
self.get_source_segment: Callable[[ast.AST], str] = partial(
|
|
44
|
+
ast.get_source_segment, source_code
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def fully_qualified_name(self) -> str:
|
|
49
|
+
return (
|
|
50
|
+
f'{self.parent.fully_qualified_name}.{self.name}'
|
|
51
|
+
if self.parent
|
|
52
|
+
else self.name
|
|
53
|
+
)
|