docstring-tailor 0.1.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.
- docstring_tailor-0.1.0/.gitignore +57 -0
- docstring_tailor-0.1.0/LICENSE +21 -0
- docstring_tailor-0.1.0/PKG-INFO +153 -0
- docstring_tailor-0.1.0/README.md +120 -0
- docstring_tailor-0.1.0/makefile +54 -0
- docstring_tailor-0.1.0/pyproject.toml +44 -0
- docstring_tailor-0.1.0/src/docstring_tailor/__init__.py +1 -0
- docstring_tailor-0.1.0/src/docstring_tailor/cli_config.py +25 -0
- docstring_tailor-0.1.0/src/docstring_tailor/constants.py +50 -0
- docstring_tailor-0.1.0/src/docstring_tailor/docstring_visitor.py +269 -0
- docstring_tailor-0.1.0/src/docstring_tailor/main.py +107 -0
- docstring_tailor-0.1.0/src/docstring_tailor/multi_line_docstring_formatter.py +474 -0
- docstring_tailor-0.1.0/src/docstring_tailor/utils.py +70 -0
- docstring_tailor-0.1.0/tests/fixtures/formatted/__init__.py +1 -0
- docstring_tailor-0.1.0/tests/fixtures/formatted/all_docstring_types_100.py +63 -0
- docstring_tailor-0.1.0/tests/fixtures/raw/__init__.py +1 -0
- docstring_tailor-0.1.0/tests/fixtures/raw/all_docstring_types_too_long.py +30 -0
- docstring_tailor-0.1.0/tests/fixtures/raw/all_docstring_types_too_short.py +97 -0
- docstring_tailor-0.1.0/tests/fixtures/raw/function_docstring_complex.py +84 -0
- docstring_tailor-0.1.0/tests/test_docstring_visitor.py +37 -0
- docstring_tailor-0.1.0/uv.lock +549 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Folders
|
|
2
|
+
__pycache__/
|
|
3
|
+
.vscode/
|
|
4
|
+
.ruff_cache/
|
|
5
|
+
.ipynb_checkpoints/
|
|
6
|
+
artifacts/
|
|
7
|
+
data/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
venv/
|
|
11
|
+
.venv/
|
|
12
|
+
.env/
|
|
13
|
+
|
|
14
|
+
# Python bytecode
|
|
15
|
+
*.pyc
|
|
16
|
+
*.pyo
|
|
17
|
+
*.pyd
|
|
18
|
+
|
|
19
|
+
# Test and coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
.coverage
|
|
22
|
+
.coverage.*
|
|
23
|
+
*.cover
|
|
24
|
+
.cache
|
|
25
|
+
.nox/
|
|
26
|
+
|
|
27
|
+
# Packaging and build
|
|
28
|
+
build/
|
|
29
|
+
dist/
|
|
30
|
+
*.egg-info/
|
|
31
|
+
.eggs/
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Logs
|
|
36
|
+
*.log
|
|
37
|
+
*.out
|
|
38
|
+
*.err
|
|
39
|
+
|
|
40
|
+
# OS-specific files (macOS + Windows)
|
|
41
|
+
.DS_Store
|
|
42
|
+
.AppleDouble
|
|
43
|
+
._*
|
|
44
|
+
Thumbs.db
|
|
45
|
+
Desktop.ini
|
|
46
|
+
|
|
47
|
+
# Temporary and backup files
|
|
48
|
+
*.tmp
|
|
49
|
+
*.temp
|
|
50
|
+
*.bak
|
|
51
|
+
*.swp
|
|
52
|
+
*.swo
|
|
53
|
+
|
|
54
|
+
# Project-specific
|
|
55
|
+
bitmaps/.~lock*
|
|
56
|
+
bitmaps/.~lock.*#
|
|
57
|
+
**/readme.todo
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Auke Bruinsma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docstring-tailor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automatic formatting of Python docstrings according to PEP 257
|
|
5
|
+
Author-email: Auke Bruinsma <afbruinsma@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Auke Bruinsma
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Python: >=3.11
|
|
29
|
+
Requires-Dist: libcst>=1.8.6
|
|
30
|
+
Requires-Dist: logging>=0.4.9.6
|
|
31
|
+
Requires-Dist: typer>=0.26.4
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# Docstring Tailor 🪡
|
|
35
|
+
|
|
36
|
+
Automatic formatting of Python docstrings according to PEP 257 and a predefined maximum number of chacacters per line.
|
|
37
|
+
|
|
38
|
+
## Docstring conventions according to PEP 257
|
|
39
|
+
|
|
40
|
+
See https://peps.python.org/pep-0257/ for the complete document.
|
|
41
|
+
|
|
42
|
+
**What is a docstring?** A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the `__doc__` special attribute of that object.
|
|
43
|
+
|
|
44
|
+
## Different types and forms of docstrings
|
|
45
|
+
|
|
46
|
+
The PEP document makes distinctions between different types of docstrings. For some docstring properties, the convention depends on the kind of object it belongs to. For module docstrings, it can also further depend on the type of python file. Therefore, a distinction is made between these **types** of docstrings:
|
|
47
|
+
|
|
48
|
+
**Four types of docstrings**:
|
|
49
|
+
1. Module docstrings
|
|
50
|
+
- Module docstrings for scripts (stand-alone program)
|
|
51
|
+
- Module docstrings for `__init__.py` files
|
|
52
|
+
- Module docstrings for 'normal' modules.
|
|
53
|
+
2. Class docstrings
|
|
54
|
+
3. Method or function docstrings
|
|
55
|
+
|
|
56
|
+
Besides the types, docstrings can occur in two different **forms**.
|
|
57
|
+
|
|
58
|
+
**Two forms of docstrings**:
|
|
59
|
+
1. One-line docstrings
|
|
60
|
+
2. Multi-line docstrings
|
|
61
|
+
|
|
62
|
+
### Conventions for one-line docstrings
|
|
63
|
+
1. Triple quotes are used even though the string fits on one line. This makes it easy to later expand it.
|
|
64
|
+
2. The closing quotes are on the same line as the opening quotes. This looks better for one-liners.
|
|
65
|
+
3. There’s no blank line either before or after the docstring, except when the the type of docstring is a class docstring. Then there should be a blank line after the docstring.
|
|
66
|
+
4. The docstring is a phrase ending in a period. It prescribes the function or method’s effect as a command (“Do this”, “Return that”), not as a description; e.g. don’t write “Returns the pathname …”.
|
|
67
|
+
5. The one-line docstring should NOT be a “signature” reiterating the function/method parameters (which can be obtained by introspection).
|
|
68
|
+
|
|
69
|
+
### Conventions for multi-line docstrings
|
|
70
|
+
1. Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description. The summary line may be used by automatic indexing tools; it is important that it fits on one line and is separated from the rest of the docstring by a blank line.
|
|
71
|
+
2. The summary line may be on the same line as the opening quotes or on the next line.
|
|
72
|
+
3. The entire docstring is indented the same as the quotes at its first line.
|
|
73
|
+
4. Insert a blank line after all docstrings (one-line or multi-line) that document a class.
|
|
74
|
+
5. Blank lines should be removed from the beginning and end of the docstring.
|
|
75
|
+
|
|
76
|
+
#### Module docstrings
|
|
77
|
+
|
|
78
|
+
5. The docstring for a module should generally list the classes, exceptions and functions (and any other objects) that are exported by the module, with a one-line summary of each. (These summaries generally give less detail than the summary line in the object’s docstring.)
|
|
79
|
+
6. The docstring of a script (a stand-alone program) should be usable as its “usage” message, printed when the script is invoked with incorrect or missing arguments (or perhaps with a “-h” option, for “help”)
|
|
80
|
+
7. The docstring for a package (i.e., the docstring of the package’s `__init__.py` module) should also list the modules and subpackages exported by the package.
|
|
81
|
+
|
|
82
|
+
#### Function or method docstrings
|
|
83
|
+
|
|
84
|
+
8. The docstring for a function or method should summarize its behavior and document its arguments, return value(s), side effects, exceptions raised, and restrictions on when it can be called (all if applicable). Optional arguments should be indicated. It should be documented whether keyword arguments are part of the interface.
|
|
85
|
+
|
|
86
|
+
#### Class docstrings
|
|
87
|
+
|
|
88
|
+
9. The docstring for a class should summarize its behavior and list the public methods and instance variables. If the class is intended to be subclassed, and has an additional interface for subclasses, this interface should be listed separately (in the docstring). The class constructor should be documented in the docstring for its __init__ method. Individual methods should be documented by their own docstring.
|
|
89
|
+
10. If a class subclasses another class and its behavior is mostly inherited from that class, its docstring should mention this and summarize the differences.
|
|
90
|
+
|
|
91
|
+
## Formatting operations applied by this tool
|
|
92
|
+
|
|
93
|
+
**How does this tool detect docstrings?**: All string literals that start with triple double quotes (""") are recognized as docstrings and will potentially be formatted.
|
|
94
|
+
|
|
95
|
+
**One-line docstrings**
|
|
96
|
+
- Regarding the 5 conventions mentioned above for one-line docstrings, only convention number 2 is enforced (The closing quotes are on the same line as the opening quotes).
|
|
97
|
+
- It is the user's reponsibility to adhere to convention number 1, since the triple quotes are used by this tool to detect the docstring. The same goes for convention number 3, 4 and 5.
|
|
98
|
+
|
|
99
|
+
- Besides the conventions mentioned above, the docstring is formatted according to a pre-defined maximum number of characters per line (**line length**). This means:
|
|
100
|
+
- If a docstring is spread out over multiple lines, but it could fit on one line, it will be converted to a one-line docstring.
|
|
101
|
+
- If a docstring exceeds the line length, it will be converted to a multi-line docstring.
|
|
102
|
+
|
|
103
|
+
**Multi-line docstrings**
|
|
104
|
+
- Regarding the conventions for multi-line docstrings mentioned above, number 2 is applied. This means if the summary line is on the next line, it will be enforced on the same line as the opening triple double quotes.
|
|
105
|
+
- Convention number 5 is also enforced, blank lines at the start and end of the docstring are removed.
|
|
106
|
+
- Most of the other conventions are about the content of the docstring, which are not checked by this tool.
|
|
107
|
+
|
|
108
|
+
Next to that, the layout of the docstring is preserved. For now the focus is on the 'Google' type docstring format, which in its most basic form, looks like this.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
|
|
112
|
+
"""Example function with PEP 484 type annotations.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
param1: The first parameter.
|
|
116
|
+
param2: The second parameter.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The return value. True for success, False otherwise.
|
|
120
|
+
"""
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Or it can look like this:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
def example_generator(n):
|
|
127
|
+
"""Generators have a ``Yields`` section instead of a ``Returns`` section.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
n (int): The upper limit of the range to generate, from 0 to `n` - 1.
|
|
131
|
+
|
|
132
|
+
Yields:
|
|
133
|
+
int: The next number in the range of 0 to `n` - 1.
|
|
134
|
+
|
|
135
|
+
Examples:
|
|
136
|
+
Examples should be written in doctest format, and should illustrate how
|
|
137
|
+
to use the function.
|
|
138
|
+
|
|
139
|
+
>>> print([i for i in example_generator(4)])
|
|
140
|
+
[0, 1, 2, 3]
|
|
141
|
+
|
|
142
|
+
"""
|
|
143
|
+
for i in range(n):
|
|
144
|
+
yield i
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Maintaining this structure, while enforcing a maximum characters per line, means the following rules have to be implented in the formatting logic.
|
|
148
|
+
|
|
149
|
+
- If the user starts a new line, even though there is still space on the current line for the next word, it should be corrected and the word should be moved to the current line.
|
|
150
|
+
- If the line is too long, the part that exceed the line limit should be moved to the next line.
|
|
151
|
+
- If the user uses two '\n' values, it means this was a deliberate choice (for example, starting the 'Args' section) and this should be preserved.
|
|
152
|
+
- Single '\n' characters in for example the 'Args' section should be preserved, as each parameter should start on a new line.
|
|
153
|
+
- If the docstring contains an 'Example' or 'Examples' section, the indentation for the code part and the code itself (indicated with '>>>' and '...') should be untouched, as this code should be able to be interpreted.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Docstring Tailor 🪡
|
|
2
|
+
|
|
3
|
+
Automatic formatting of Python docstrings according to PEP 257 and a predefined maximum number of chacacters per line.
|
|
4
|
+
|
|
5
|
+
## Docstring conventions according to PEP 257
|
|
6
|
+
|
|
7
|
+
See https://peps.python.org/pep-0257/ for the complete document.
|
|
8
|
+
|
|
9
|
+
**What is a docstring?** A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the `__doc__` special attribute of that object.
|
|
10
|
+
|
|
11
|
+
## Different types and forms of docstrings
|
|
12
|
+
|
|
13
|
+
The PEP document makes distinctions between different types of docstrings. For some docstring properties, the convention depends on the kind of object it belongs to. For module docstrings, it can also further depend on the type of python file. Therefore, a distinction is made between these **types** of docstrings:
|
|
14
|
+
|
|
15
|
+
**Four types of docstrings**:
|
|
16
|
+
1. Module docstrings
|
|
17
|
+
- Module docstrings for scripts (stand-alone program)
|
|
18
|
+
- Module docstrings for `__init__.py` files
|
|
19
|
+
- Module docstrings for 'normal' modules.
|
|
20
|
+
2. Class docstrings
|
|
21
|
+
3. Method or function docstrings
|
|
22
|
+
|
|
23
|
+
Besides the types, docstrings can occur in two different **forms**.
|
|
24
|
+
|
|
25
|
+
**Two forms of docstrings**:
|
|
26
|
+
1. One-line docstrings
|
|
27
|
+
2. Multi-line docstrings
|
|
28
|
+
|
|
29
|
+
### Conventions for one-line docstrings
|
|
30
|
+
1. Triple quotes are used even though the string fits on one line. This makes it easy to later expand it.
|
|
31
|
+
2. The closing quotes are on the same line as the opening quotes. This looks better for one-liners.
|
|
32
|
+
3. There’s no blank line either before or after the docstring, except when the the type of docstring is a class docstring. Then there should be a blank line after the docstring.
|
|
33
|
+
4. The docstring is a phrase ending in a period. It prescribes the function or method’s effect as a command (“Do this”, “Return that”), not as a description; e.g. don’t write “Returns the pathname …”.
|
|
34
|
+
5. The one-line docstring should NOT be a “signature” reiterating the function/method parameters (which can be obtained by introspection).
|
|
35
|
+
|
|
36
|
+
### Conventions for multi-line docstrings
|
|
37
|
+
1. Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description. The summary line may be used by automatic indexing tools; it is important that it fits on one line and is separated from the rest of the docstring by a blank line.
|
|
38
|
+
2. The summary line may be on the same line as the opening quotes or on the next line.
|
|
39
|
+
3. The entire docstring is indented the same as the quotes at its first line.
|
|
40
|
+
4. Insert a blank line after all docstrings (one-line or multi-line) that document a class.
|
|
41
|
+
5. Blank lines should be removed from the beginning and end of the docstring.
|
|
42
|
+
|
|
43
|
+
#### Module docstrings
|
|
44
|
+
|
|
45
|
+
5. The docstring for a module should generally list the classes, exceptions and functions (and any other objects) that are exported by the module, with a one-line summary of each. (These summaries generally give less detail than the summary line in the object’s docstring.)
|
|
46
|
+
6. The docstring of a script (a stand-alone program) should be usable as its “usage” message, printed when the script is invoked with incorrect or missing arguments (or perhaps with a “-h” option, for “help”)
|
|
47
|
+
7. The docstring for a package (i.e., the docstring of the package’s `__init__.py` module) should also list the modules and subpackages exported by the package.
|
|
48
|
+
|
|
49
|
+
#### Function or method docstrings
|
|
50
|
+
|
|
51
|
+
8. The docstring for a function or method should summarize its behavior and document its arguments, return value(s), side effects, exceptions raised, and restrictions on when it can be called (all if applicable). Optional arguments should be indicated. It should be documented whether keyword arguments are part of the interface.
|
|
52
|
+
|
|
53
|
+
#### Class docstrings
|
|
54
|
+
|
|
55
|
+
9. The docstring for a class should summarize its behavior and list the public methods and instance variables. If the class is intended to be subclassed, and has an additional interface for subclasses, this interface should be listed separately (in the docstring). The class constructor should be documented in the docstring for its __init__ method. Individual methods should be documented by their own docstring.
|
|
56
|
+
10. If a class subclasses another class and its behavior is mostly inherited from that class, its docstring should mention this and summarize the differences.
|
|
57
|
+
|
|
58
|
+
## Formatting operations applied by this tool
|
|
59
|
+
|
|
60
|
+
**How does this tool detect docstrings?**: All string literals that start with triple double quotes (""") are recognized as docstrings and will potentially be formatted.
|
|
61
|
+
|
|
62
|
+
**One-line docstrings**
|
|
63
|
+
- Regarding the 5 conventions mentioned above for one-line docstrings, only convention number 2 is enforced (The closing quotes are on the same line as the opening quotes).
|
|
64
|
+
- It is the user's reponsibility to adhere to convention number 1, since the triple quotes are used by this tool to detect the docstring. The same goes for convention number 3, 4 and 5.
|
|
65
|
+
|
|
66
|
+
- Besides the conventions mentioned above, the docstring is formatted according to a pre-defined maximum number of characters per line (**line length**). This means:
|
|
67
|
+
- If a docstring is spread out over multiple lines, but it could fit on one line, it will be converted to a one-line docstring.
|
|
68
|
+
- If a docstring exceeds the line length, it will be converted to a multi-line docstring.
|
|
69
|
+
|
|
70
|
+
**Multi-line docstrings**
|
|
71
|
+
- Regarding the conventions for multi-line docstrings mentioned above, number 2 is applied. This means if the summary line is on the next line, it will be enforced on the same line as the opening triple double quotes.
|
|
72
|
+
- Convention number 5 is also enforced, blank lines at the start and end of the docstring are removed.
|
|
73
|
+
- Most of the other conventions are about the content of the docstring, which are not checked by this tool.
|
|
74
|
+
|
|
75
|
+
Next to that, the layout of the docstring is preserved. For now the focus is on the 'Google' type docstring format, which in its most basic form, looks like this.
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
|
|
79
|
+
"""Example function with PEP 484 type annotations.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
param1: The first parameter.
|
|
83
|
+
param2: The second parameter.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
The return value. True for success, False otherwise.
|
|
87
|
+
"""
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Or it can look like this:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
def example_generator(n):
|
|
94
|
+
"""Generators have a ``Yields`` section instead of a ``Returns`` section.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
n (int): The upper limit of the range to generate, from 0 to `n` - 1.
|
|
98
|
+
|
|
99
|
+
Yields:
|
|
100
|
+
int: The next number in the range of 0 to `n` - 1.
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
Examples should be written in doctest format, and should illustrate how
|
|
104
|
+
to use the function.
|
|
105
|
+
|
|
106
|
+
>>> print([i for i in example_generator(4)])
|
|
107
|
+
[0, 1, 2, 3]
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
for i in range(n):
|
|
111
|
+
yield i
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Maintaining this structure, while enforcing a maximum characters per line, means the following rules have to be implented in the formatting logic.
|
|
115
|
+
|
|
116
|
+
- If the user starts a new line, even though there is still space on the current line for the next word, it should be corrected and the word should be moved to the current line.
|
|
117
|
+
- If the line is too long, the part that exceed the line limit should be moved to the next line.
|
|
118
|
+
- If the user uses two '\n' values, it means this was a deliberate choice (for example, starting the 'Args' section) and this should be preserved.
|
|
119
|
+
- Single '\n' characters in for example the 'Args' section should be preserved, as each parameter should start on a new line.
|
|
120
|
+
- If the docstring contains an 'Example' or 'Examples' section, the indentation for the code part and the code itself (indicated with '>>>' and '...') should be untouched, as this code should be able to be interpreted.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Default project folder
|
|
2
|
+
PROJECT_NAME = src/docstring_tailor
|
|
3
|
+
|
|
4
|
+
# Format and lint code with Ruff
|
|
5
|
+
ruff:
|
|
6
|
+
uv run ruff check $(PROJECT_NAME) --fix
|
|
7
|
+
uv run ruff format $(PROJECT_NAME)
|
|
8
|
+
@echo "🔧 Successfully executed ruff."
|
|
9
|
+
|
|
10
|
+
# Static type-check code with ty
|
|
11
|
+
ty:
|
|
12
|
+
uv run ty check
|
|
13
|
+
@echo "🔍 Successfully executed ty."
|
|
14
|
+
|
|
15
|
+
# Run tests with Pytest
|
|
16
|
+
# -vvvs: Very verbose output, shows print() statements and extra test details
|
|
17
|
+
# --cov=$(PROJECT_NAME): Measure test coverage for the project
|
|
18
|
+
# --cov-report=term-missing: Show which lines are missing coverage
|
|
19
|
+
# --cov-branch: Track branch coverage, not just line coverage
|
|
20
|
+
pytest:
|
|
21
|
+
uv run pytest tests -vvvs \
|
|
22
|
+
--cov=$(PROJECT_NAME) \
|
|
23
|
+
--cov-report=term-missing \
|
|
24
|
+
--cov-branch
|
|
25
|
+
@echo "🧪 Successfully executed pytest."
|
|
26
|
+
|
|
27
|
+
# Remove caches and temporary files
|
|
28
|
+
clean:
|
|
29
|
+
@find . -type d \( \
|
|
30
|
+
-name '__pycache__' -o \
|
|
31
|
+
-name '.ruff_cache' -o \
|
|
32
|
+
-name '.mypy_cache' -o \
|
|
33
|
+
-name '.pytest_cache' \
|
|
34
|
+
\) -exec rm -rf {} +
|
|
35
|
+
@rm -f .coverage .python-version
|
|
36
|
+
@rm -rf artifacts
|
|
37
|
+
@echo "🧹 Successfully cleaned project."
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Commit and push everything to git
|
|
41
|
+
git:
|
|
42
|
+
git add -A
|
|
43
|
+
git commit -m "Updated"
|
|
44
|
+
git push
|
|
45
|
+
@echo "📤 Successfully executed git."
|
|
46
|
+
|
|
47
|
+
# Run full workflow: format, type-check, test, clean, commit
|
|
48
|
+
all:
|
|
49
|
+
make ruff
|
|
50
|
+
make ty
|
|
51
|
+
make pytest
|
|
52
|
+
make clean
|
|
53
|
+
make git
|
|
54
|
+
@echo "⚡ Successfully executed all tasks."
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "docstring-tailor"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Automatic formatting of Python docstrings according to PEP 257"
|
|
5
|
+
authors = [{ name = "Auke Bruinsma", email = "afbruinsma@gmail.com" }]
|
|
6
|
+
license = { file = "LICENSE" }
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"libcst>=1.8.6",
|
|
11
|
+
"logging>=0.4.9.6",
|
|
12
|
+
"typer>=0.26.4",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[dependency-groups]
|
|
16
|
+
dev = [
|
|
17
|
+
"prek>=0.3.8",
|
|
18
|
+
"pytest>=8.4.2",
|
|
19
|
+
"pytest-cov>=7.0.0",
|
|
20
|
+
"ruff>=0.11.6",
|
|
21
|
+
"ty>=0.0.29",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[tool.ruff.lint]
|
|
25
|
+
select = [
|
|
26
|
+
"I", # isort-style import sorting
|
|
27
|
+
"ANN", # annotation rules
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.ruff.lint.isort]
|
|
31
|
+
known-first-party = ["src"]
|
|
32
|
+
|
|
33
|
+
[tool.pytest.ini_options]
|
|
34
|
+
pythonpath = ["."]
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["hatchling"]
|
|
38
|
+
build-backend = "hatchling.build"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/docstring_tailor"]
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
docstring_tailor = "docstring_tailor.main:app"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
""""""
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""CLI configuration constants and allowed values for docstring_tailor."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
# Initial argument that specifies the file(s) and/or folder(s)
|
|
6
|
+
DEFAULT_PATHS = [("src")]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Argument: '--style'
|
|
10
|
+
class DocstringStyle(str, Enum):
|
|
11
|
+
"""Supported docstring styles."""
|
|
12
|
+
|
|
13
|
+
google = "google"
|
|
14
|
+
numpy = "numpy"
|
|
15
|
+
sphinx = "sphinx"
|
|
16
|
+
epydoc = "epydoc"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
SUPPORTED_STYLES = {DocstringStyle.google}
|
|
20
|
+
DEFAULT_STYLE = DocstringStyle.google
|
|
21
|
+
|
|
22
|
+
# Argument: '--line-length'
|
|
23
|
+
LINE_LENGTH_MIN = 30
|
|
24
|
+
LINE_LENGTH_MAX = 300
|
|
25
|
+
LINE_LENGTH_DEFAULT = 100
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Module for storing project constants."""
|
|
2
|
+
|
|
3
|
+
# Encoding for reading .py files.
|
|
4
|
+
ENCODING: str = "utf-8"
|
|
5
|
+
|
|
6
|
+
# Docstring delimiters.
|
|
7
|
+
DOCSTRING_DELIMITER: str = '"""'
|
|
8
|
+
DOCSTRING_DELIMITER_LENGTH: int = len(DOCSTRING_DELIMITER)
|
|
9
|
+
|
|
10
|
+
# Google-style docstring section keywords.
|
|
11
|
+
GOOGLE_PLAIN_SECTIONS = frozenset(
|
|
12
|
+
{"Note", "Notes", "References", "See Also", "Todo", "Warning", "Warnings"}
|
|
13
|
+
)
|
|
14
|
+
GOOGLE_ITEM_SECTIONS = frozenset(
|
|
15
|
+
{"Args", "Arguments", "Attributes", "Raises", "Returns", "Yields"}
|
|
16
|
+
)
|
|
17
|
+
GOOGLE_CODE_SECTIONS = frozenset({"Example", "Examples"})
|
|
18
|
+
GOOGLE_SECTION_HEADERS = (
|
|
19
|
+
GOOGLE_PLAIN_SECTIONS | GOOGLE_ITEM_SECTIONS | GOOGLE_CODE_SECTIONS
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# NumPy-style docstring section keywords.
|
|
23
|
+
NUMPY_ITEM_SECTIONS = frozenset(
|
|
24
|
+
{
|
|
25
|
+
"Attributes",
|
|
26
|
+
"Methods",
|
|
27
|
+
"Other Parameters",
|
|
28
|
+
"Parameters",
|
|
29
|
+
"Raises",
|
|
30
|
+
"Receives",
|
|
31
|
+
"Returns",
|
|
32
|
+
"Yields",
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
NUMPY_PLAIN_SECTIONS = frozenset({"Examples", "Notes", "References", "See Also"})
|
|
36
|
+
NUMPY_SECTION_HEADERS = NUMPY_ITEM_SECTIONS | NUMPY_PLAIN_SECTIONS
|
|
37
|
+
|
|
38
|
+
# Sphinx/reST-style docstring directive markers.
|
|
39
|
+
# Directive-based rather than section-based — no section headers in the Google/NumPy sense.
|
|
40
|
+
SPHINX_ITEM_DIRECTIVES = frozenset({":param", ":raises", ":returns", ":rtype", ":type"})
|
|
41
|
+
SPHINX_PLAIN_DIRECTIVES = frozenset(
|
|
42
|
+
{".. example::", ".. note::", ".. seealso::", ".. warning::"}
|
|
43
|
+
)
|
|
44
|
+
SPHINX_DIRECTIVES = SPHINX_ITEM_DIRECTIVES | SPHINX_PLAIN_DIRECTIVES
|
|
45
|
+
|
|
46
|
+
# Epydoc-style docstring tag markers.
|
|
47
|
+
# Tag-based rather than section-based — no section headers in the Google/NumPy sense.
|
|
48
|
+
EPYDOC_ITEM_TAGS = frozenset({"@param", "@raise", "@return", "@rtype", "@type"})
|
|
49
|
+
EPYDOC_PLAIN_TAGS = frozenset({"@note", "@warning"})
|
|
50
|
+
EPYDOC_TAGS = EPYDOC_ITEM_TAGS | EPYDOC_PLAIN_TAGS
|