docstring-tailor 0.3.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.
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/PKG-INFO +70 -12
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/README.md +69 -11
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/makefile +1 -1
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/pyproject.toml +1 -1
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/cli_config.py +1 -2
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/constants.py +55 -3
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/ir_model.py +7 -2
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/main.py +12 -4
- docstring_tailor-0.4.0/src/docstring_tailor/parser/directive_based/sphinx_docstring_parser.py +577 -0
- docstring_tailor-0.3.0/src/docstring_tailor/parser/indentation_based/indentation_based_parser.py → docstring_tailor-0.4.0/src/docstring_tailor/parser/docstring_parser_base.py +28 -179
- docstring_tailor-0.4.0/src/docstring_tailor/parser/indentation_based/indentation_based_parser.py +200 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/parser/parser_factory.py +10 -8
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/renderer/base_renderer.py +10 -6
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/renderer/google_renderer.py +20 -10
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/renderer/numpy_renderer.py +12 -7
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/renderer/renderer_factory.py +2 -0
- docstring_tailor-0.4.0/src/docstring_tailor/renderer/sphinx_renderer.py +286 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_keyword_translation.py +115 -35
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/tests/cases/formatting_cases.py +16 -16
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/uv.lock +1 -1
- docstring_tailor-0.3.0/temp.md +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/.gitignore +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/LICENSE +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/__init__.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/docstring_visitor.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/parser/indentation_based/google_docstring_parser.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/parser/indentation_based/numpy_docstring_parser.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/parser/indentation_based/structured_list_parser.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/__init__.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_cli.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_file_system.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_formatting.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_list_detection.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_parsing.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/src/docstring_tailor/utils/utils_printing.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/tests/cases/__init__.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/tests/cases/config_model.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/class_docstring/class_docstring_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/class_docstring/class_docstring_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/class_docstring/class_docstring_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_block_multiple/code_block_multiple_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_block_multiple/code_block_multiple_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_block_singular/code_block_singular_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_block_singular/code_block_singular_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_repl_multiple/code_repl_multiple_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_repl_multiple/code_repl_multiple_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_repl_singular/code_repl_singular_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/code_repl_singular/code_repl_singular_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/empty/empty_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/empty/empty_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/empty/empty_no_space.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_code_block/named_paragraph_code_block_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_code_block/named_paragraph_code_block_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_code_repl/named_paragraph_code_repl_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_code_repl/named_paragraph_code_repl_blank_lines.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_paragraph/named_paragraph_paragraph_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_paragraph/named_paragraph_paragraph_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_paragraph/named_paragraph_paragraph_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/named_paragraph_paragraph/named_paragraph_paragraph_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_and_simple_list/paragraph_and_simple_list_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_and_simple_list/paragraph_and_simple_list_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_and_simple_list/paragraph_and_simple_list_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_and_simple_list/paragraph_and_simple_list_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_multi_line/paragraph_multi_line_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_multi_line/paragraph_multi_line_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_multi_line/paragraph_multi_line_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_multi_line/paragraph_multi_line_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_one_line/paragraph_one_line_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_one_line/paragraph_one_line_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_one_line/paragraph_one_line_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/paragraph_one_line/paragraph_one_line_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/simple_list/simple_list_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/simple_list/simple_list_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/simple_list/simple_list_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/simple_list/simple_list_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/structured_list/structured_list_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/structured_list/structured_list_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/structured_list/structured_list_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/docstring_elements/structured_list/structured_list_wrong_input.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/function_docstring/function_docstring_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/function_docstring/function_docstring_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/function_docstring/function_docstring_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/module_docstring/module_docstring_100.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/module_docstring/module_docstring_60.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/module_docstring/module_docstring_80.py +0 -0
- {docstring_tailor-0.3.0/tests/fixtures → docstring_tailor-0.4.0/tests/fixtures/google}/readme_examples/readme_examples.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/tests/test_docstring_tailor.py +0 -0
- {docstring_tailor-0.3.0 → docstring_tailor-0.4.0}/tests/utils/utils_testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docstring-tailor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Formats Python docstrings to PEP 257 style with configurable line length.
|
|
5
5
|
Author-email: Auke Bruinsma <afbruinsma@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -116,7 +116,7 @@ line-length = 88
|
|
|
116
116
|
line-length = 88
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
Define a docstring style.
|
|
119
|
+
Define a docstring style. Three styles are currently supported: [Google](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html), [NumPy](https://numpydoc.readthedocs.io/en/latest/format.html), and [Sphinx](https://www.sphinx-doc.org/en/master/usage/domains/python.html#info-field-lists). The style always has to be configured explicitly.
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
122
|
uv run docstring_tailor format --style numpy
|
|
@@ -165,20 +165,20 @@ If no paths are provided, `docstring_tailor` will attempt to locate and format f
|
|
|
165
165
|
|
|
166
166
|
| <div style="width:140px">Option</div> | <div style="width:50px">Type</div> | <div style="width:80px">Default</div> | Description |
|
|
167
167
|
|---|---|---|---|
|
|
168
|
-
| `--line-length` | `int` | 100
|
|
169
|
-
| `--style` | `str` |
|
|
170
|
-
| `--exclude` | `str` | —
|
|
171
|
-
| `--diff` | flag | —
|
|
168
|
+
| `--line-length` | `int` | 100 | Maximum number of characters allowed per line after formatting. |
|
|
169
|
+
| `--style` | `str` | *required* | Docstring style to format to. `google`, `numpy` or `sphinx`. |
|
|
170
|
+
| `--exclude` | `str` | — | A glob pattern for paths to exclude. Can be passed multiple times. Single-path patterns (e.g. `tests`, `*.pyi`) match by name anywhere in the tree. Relative patterns (e.g. `src/generated/*.py`) match against the path relative to the project root. |
|
|
171
|
+
| `--diff` | flag | — | Print a unified diff of changes to stdout instead of modifying files. No files are written when this flag is set. |
|
|
172
172
|
|
|
173
173
|
#### `convert`
|
|
174
174
|
|
|
175
175
|
| <div style="width:140px">Option</div> | <div style="width:50px">Type</div> | <div style="width:80px">Default</div> | Description |
|
|
176
176
|
|---|---|---|---|
|
|
177
|
-
| `--from-style` | `str` | *required* | Docstring style to convert from. `google` or `
|
|
178
|
-
| `--to-style` | `str` | *required* | Docstring style to convert to. `google` or `
|
|
179
|
-
| `--line-length` | `int` | 100
|
|
180
|
-
| `--exclude` | `str` | —
|
|
181
|
-
| `--diff` | flag | —
|
|
177
|
+
| `--from-style` | `str` | *required* | Docstring style to convert from. `google`, `numpy` or `sphinx`. |
|
|
178
|
+
| `--to-style` | `str` | *required* | Docstring style to convert to. `google`, `numpy` or `sphinx`. Must differ from `--from-style`. |
|
|
179
|
+
| `--line-length` | `int` | 100 | Maximum number of characters allowed per line after formatting. |
|
|
180
|
+
| `--exclude` | `str` | — | A glob pattern for paths to exclude. Can be passed multiple times. Single-path patterns (e.g. `tests`, `*.pyi`) match by name anywhere in the tree. Relative patterns (e.g. `src/generated/*.py`) match against the path relative to the project root. |
|
|
181
|
+
| `--diff` | flag | — | Print a unified diff of changes to stdout instead of modifying files. No files are written when this flag is set. |
|
|
182
182
|
|
|
183
183
|
`--from-style` and `--to-style` have no config-file or default fallback — both must be given explicitly on every `convert` invocation, and must be different from each other.
|
|
184
184
|
|
|
@@ -408,6 +408,47 @@ def example_function(example_argument_1: str, example_argument_2: int) -> str:
|
|
|
408
408
|
- In the `Examples` section, start the Python REPL with `>>>` and use `...` for continuation lines, matching Pydoc conventions — same as Google style.
|
|
409
409
|
- These same section keywords can also be used in module or class docstrings — for example, a `Parameters` section in a class docstring, or an `Examples` section in a module docstring.
|
|
410
410
|
|
|
411
|
+
**Sphinx / reST**
|
|
412
|
+
|
|
413
|
+
```python
|
|
414
|
+
def example_function(example_argument_1: str, example_argument_2: int) -> str:
|
|
415
|
+
"""Demonstrates a Sphinx-style function docstring with multiple
|
|
416
|
+
sections.
|
|
417
|
+
|
|
418
|
+
This function exists purely as a formatting example and
|
|
419
|
+
illustrates how parameters, return values, and raised exceptions
|
|
420
|
+
are documented using reStructuredText info fields.
|
|
421
|
+
|
|
422
|
+
:param example_argument_1: First example input value used to
|
|
423
|
+
construct a formatted result string.
|
|
424
|
+
:type example_argument_1: str
|
|
425
|
+
:param example_argument_2: Second example input value used to
|
|
426
|
+
influence the transformation logic.
|
|
427
|
+
:type example_argument_2: int
|
|
428
|
+
:returns: A formatted string combining both input arguments into a
|
|
429
|
+
single human-readable representation.
|
|
430
|
+
:rtype: str
|
|
431
|
+
:raises ValueError: Raised when example_argument_2 is negative or
|
|
432
|
+
zero, as only positive integers are considered valid in this
|
|
433
|
+
demonstration.
|
|
434
|
+
|
|
435
|
+
.. note::
|
|
436
|
+
Additional informational directives such as ``.. note::`` and
|
|
437
|
+
``.. warning::`` are recognized and preserved during
|
|
438
|
+
formatting.
|
|
439
|
+
"""
|
|
440
|
+
if example_argument_2 <= 0:
|
|
441
|
+
raise ValueError("example_argument_2 must be positive")
|
|
442
|
+
|
|
443
|
+
return f"{example_argument_1}-{example_argument_2}"
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
- Parameters are documented with `:param name: description` info fields, and their types with a separate `:type name: type` field. An inline form (`:param str name: description`) is also accepted on input and is split into the two-field form on output.
|
|
447
|
+
- Types are genuinely optional in reST: a `:param:` without a matching `:type:` is preserved as-is, and `docstring_tailor` never fabricates a type when one is absent.
|
|
448
|
+
- Return values use `:returns:` (with `:return:` accepted as an alias), and the return type uses `:rtype:`.
|
|
449
|
+
- Raised exceptions use `:raises Exception: description` (`:raise`, `:except` and `:exception` are accepted as aliases).
|
|
450
|
+
- Informational directives such as `.. note::`, `.. warning::`, `.. seealso::` and `.. example::` are recognized and their indented bodies are formatted while the directive header is preserved.
|
|
451
|
+
|
|
411
452
|
### Codeblocks
|
|
412
453
|
|
|
413
454
|
**Google / Numpy** (identical for this example)
|
|
@@ -556,7 +597,11 @@ Steps:
|
|
|
556
597
|
|
|
557
598
|
### 60 characters per line — The Minimalist Monk 🧘
|
|
558
599
|
|
|
559
|
-
You believe every character has a purpose and every extra column is a personal failure 😤. You keep your docstrings short, your functions tiny, and your emotional attachment to whitespace surprisingly strong.
|
|
600
|
+
You believe every character has a purpose and every extra column is a personal failure 😤. You keep your docstrings short, your functions tiny, and your emotional attachment to whitespace surprisingly strong. Variable names? Anything longer than two characters is wasteful bloat — x, y, z, and i are sufficient for any problem. Docstrings are memory theft; everything the code needs to say should be obvious from context or inferred through pure spiritual understanding 🙏. Why document when you could just make the code so minimalist that it transcends the need for explanation? Your motto: if it takes more than 60 characters to explain, the explanation itself is the bug, not the code.
|
|
601
|
+
|
|
602
|
+
### 79 characters per line — The Precision Tuner ⚙️
|
|
603
|
+
|
|
604
|
+
You didn't choose 79 characters; you derived it through first principles and a spreadsheet. You read every formatter's GitHub issues, every style guide's rationale, and you have strong opinions about why 80 is overrated but 78 is cowardice 😤. You've A/B tested readability on three different monitors, measured your own eye-tracking data, and lost sleep over whether \n counts toward the limit or not. You configure your linter to lint your linter, and you have a .editorconfig file that is longer than most people's actual code 📋. You know exactly why PEP 8 suggested 79 and you've defended this choice at dinner parties with the fervor of someone protecting their firstborn child 🛡️. You don't just use docstring_tailor; you've benchmarked it against seven alternatives and created a spreadsheet ranking their consistency. Your line length is not a preference—it's a thesis 📊. You sleep well knowing that you have optimized, and the universe is in perfect order, exactly 79 characters wide.
|
|
560
605
|
|
|
561
606
|
### 80 characters per line — The Digital Archaeologist 🦖
|
|
562
607
|
|
|
@@ -585,6 +630,8 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
585
630
|
| <div style="width:70px">Resource</div> | <div style="width:100px">Description</div> | <div style="width:130px">Link</div>
|
|
586
631
|
|---|---|---|
|
|
587
632
|
| PEP 257 - Docstring Conventions | Documents the semantics and conventions associated with Python docstrings. | [Link](https://peps.python.org/pep-0257/) |
|
|
633
|
+
| PEP 287 - reStructuredText Docstring Format | Specifies a reStructuredText-based markup convention for Python docstrings, the basis of the Sphinx/reST style. | [Link](https://peps.python.org/pep-0287) |
|
|
634
|
+
| PEP 484 - Type Hints | Provides a standard syntax for type annotations in Python. | [Link](https://peps.python.org/pep-0484/) |
|
|
588
635
|
| Google Python Style Guide | Lists *dos and don'ts* for Python programs. | [Link](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings) |
|
|
589
636
|
| Numpy Style Guide | Describes the syntax and best practices for docstrings used with the numpydoc extension for Sphinx | [Link](https://numpydoc.readthedocs.io/en/latest/format.html) |
|
|
590
637
|
| Types of indentation | Wikipedia article that defines different kinds of indentation | [Link](https://en.wikipedia.org/wiki/Indentation_(typesetting)) |
|
|
@@ -605,6 +652,8 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
605
652
|
| `0.2.0` | 2026-06-07 | Feature update | <ul><li>Implemented the `detect-lists` parameter, adding support for unordered and ordered (numbered) lists in docstrings. When enabled, list structures are detected automatically and each list item is formatted onto its own line.</li><li>Introduced a declarative golden-file test framework for formatter validation. Test cases are now generated from parametrized templates using Cartesian-product expansion, significantly reducing boilerplate and improving scalability for configuration coverage.</li><li>Expanded this `README.md` with the 'API Overview', 'Release Notes', 'Example docstrings' and 'Roadmap' sections.</li><li>Test coverage: 75%</li></ul> |
|
|
606
653
|
| `0.2.1` | 2026-06-11 | Feature update | <ul><li>Added the `-V`/`--version` command to the CLI.</li><li>Added the `--exclude` command to the CLI.</li><li>Added the `--diff` command to the CLI.</li><li>Added the 'Demo' part to to the `README.md`.</ul> |
|
|
607
654
|
| `0.3.0` | 2026-07-20 | Feature update & bug fixes | <ul><li>Introduced a style-agnostic intermediate representation (IR) model and refactored parsing into an abstract base class hierarchy. Google and NumPy docstrings now parse into the same IR via `IndentationBasedParser` subclasses, enabling lossless conversion between styles. Structured list parsing is delegated to style-specific implementations to handle syntactic differences (Google's inline `name (type):` vs. NumPy's `name : type` on separate lines).</li><li>Refactored rendering to match the parser architecture: `DocstringRendererBase` (ABC) with style-specific subclasses that implement two hooks — section header formatting (Google's `Args:` vs. NumPy's `Parameters` + underline) and section body indentation rules (confirmed against numpy's own docstrings to keep bodies flush with headers, unlike Google). Keyword translation between styles happens automatically during conversion.</li><li>Code sections and Python REPL blocks now also can be created outside the 'Example(s)' section.</li><li>Fixed a bug when codeblock sections contain blank lines.</li><li>Fixed a bug when the docstring starts immediately with an (un)ordered list.</li><li>Removed `detect-lists` as CLI parameter, because the logic should always be applied if the docstring contains (un)ordered lists.</li><li>Changed behaviour for empty docstrings so that it consistent with Ruff.</li></ul> |
|
|
655
|
+
| `0.3.1` | 2026-07-21 | Small fixes | <ul><li>The `style` parameter does not have a default argument anymore, instead it always has to be configured explicitly by the user.</li><li>Fixed a bug where one-line docstrings inside indented scopes (e.g. class or method bodies) were wrapped to multiple lines prematurely, due to indentation being counted twice when checking against the configured line length.</li> <li>Added an exception, consistent with Ruff, allowing a one-line docstring to exceed the configured line length by up to 3 characters when only the closing triple quotes would otherwise be pushed onto their own line. This prevents docstring_tailor and Ruff from repeatedly reformatting the same docstring back and forth when both are run as pre-commit hooks.</li></ul> |
|
|
656
|
+
| `0.4.0` | 2026-07-24 | Feature update | <ul><li>Added support for the Sphinx/reST docstring `style`, covering both parsing and rendering. Sphinx docstrings now parse into the same style-agnostic intermediate representation (IR) as Google and NumPy, enabling lossless conversion in all directions between the three styles (`format --style sphinx` and `convert` to/from `sphinx`).</li><li>Extracted a shared `DocstringParserBase` holding the style-agnostic flat-content pipeline; `IndentationBasedParser` (Google/NumPy) and the new directive-based `SphinxDocstringParser` both build on it, reusing the existing pipeline rather than duplicating logic.</li><li>The Sphinx parser handles info-field lists (`:param:`/`:type:`, `:returns:`/`:rtype:`, `:raises:`), the inline parameter form (`:param str name:`), field/type pairing by name, tag aliases (`:return:`, `:raise:`, `:except:`, `:exception:`), and informational directives (`.. note::`, `.. warning::`, `.. seealso::`, `.. example::`).</li><li>The Sphinx renderer emits a contiguous info-field list with separate `:type:`/`:rtype:` lines, with hanging-indent wrapping of field bodies.</li><li>Modelled an absent parameter type as `None` in the IR (never fabricated), and updated the Google and NumPy renderers to degrade gracefully when a type is undocumented.</li><li>Reorganized the golden-file test fixtures into per-style folders (`google/`, `sphinx/`, `convert/`), with the fixture style folder derived automatically from each test case's configuration.</li></ul> |
|
|
608
657
|
|
|
609
658
|
## Roadmap
|
|
610
659
|
|
|
@@ -622,6 +671,15 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
622
671
|
- Formatting module for the remaining docstring formats (Sphinx, Epydoc), driven
|
|
623
672
|
entirely by the same IR already used for Google and NumPy.
|
|
624
673
|
|
|
674
|
+
### Finish the Sphinx/reST implementation
|
|
675
|
+
|
|
676
|
+
The core Sphinx style (parameters, returns, raises, and the common admonitions) is supported, but full coverage of every Sphinx construct is not there yet. Currently, unrecognized constructs are passed through as plain paragraph text — never dropped, but not parsed into a structured section, so they don't wrap as fields and don't convert to a Google/NumPy equivalent. The following would close that gap:
|
|
677
|
+
|
|
678
|
+
- Class attribute fields (`:ivar:`, `:cvar:`, `:var:` paired with `:vartype:`), mapped onto the same `Attributes` section Google and NumPy already expose, so class docstrings round-trip and convert like the other styles. Requires a new field-pairing path in the parser, an `Attributes` render path in the renderer, and a fix to the keyword translation tables (which currently fold Attributes into Parameters).
|
|
679
|
+
- Keyword-only argument fields (`:keyword:` / `:kwarg:` with `:kwtype:`), aliased onto the existing parameter/type handling.
|
|
680
|
+
- The broader set of admonition directives (`.. tip::`, `.. important::`, `.. caution::`, `.. attention::`, `.. hint::`, `.. danger::`, `.. error::`, `.. todo::`, `.. deprecated::`, `.. versionadded::`, `.. versionchanged::`), added to the directive-to-header map so their bodies format as named paragraphs. Headers without a Google/NumPy equivalent pass through unchanged on conversion.
|
|
681
|
+
- Literal-body directives (`.. code-block::`, `.. math::`) — more involved, because their content must be preserved verbatim and never reflowed, and there is no clean equivalent in the current IR. Needs a dedicated literal-block IR node before it can be handled safely.
|
|
682
|
+
|
|
625
683
|
### Nice to have
|
|
626
684
|
- Make sure the package can be used as a pre-commit hook.
|
|
627
685
|
- LSP (Language Server Protocol) support, enabling real-time feedback on malformed
|
|
@@ -83,7 +83,7 @@ line-length = 88
|
|
|
83
83
|
line-length = 88
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
Define a docstring style.
|
|
86
|
+
Define a docstring style. Three styles are currently supported: [Google](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html), [NumPy](https://numpydoc.readthedocs.io/en/latest/format.html), and [Sphinx](https://www.sphinx-doc.org/en/master/usage/domains/python.html#info-field-lists). The style always has to be configured explicitly.
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
uv run docstring_tailor format --style numpy
|
|
@@ -132,20 +132,20 @@ If no paths are provided, `docstring_tailor` will attempt to locate and format f
|
|
|
132
132
|
|
|
133
133
|
| <div style="width:140px">Option</div> | <div style="width:50px">Type</div> | <div style="width:80px">Default</div> | Description |
|
|
134
134
|
|---|---|---|---|
|
|
135
|
-
| `--line-length` | `int` | 100
|
|
136
|
-
| `--style` | `str` |
|
|
137
|
-
| `--exclude` | `str` | —
|
|
138
|
-
| `--diff` | flag | —
|
|
135
|
+
| `--line-length` | `int` | 100 | Maximum number of characters allowed per line after formatting. |
|
|
136
|
+
| `--style` | `str` | *required* | Docstring style to format to. `google`, `numpy` or `sphinx`. |
|
|
137
|
+
| `--exclude` | `str` | — | A glob pattern for paths to exclude. Can be passed multiple times. Single-path patterns (e.g. `tests`, `*.pyi`) match by name anywhere in the tree. Relative patterns (e.g. `src/generated/*.py`) match against the path relative to the project root. |
|
|
138
|
+
| `--diff` | flag | — | Print a unified diff of changes to stdout instead of modifying files. No files are written when this flag is set. |
|
|
139
139
|
|
|
140
140
|
#### `convert`
|
|
141
141
|
|
|
142
142
|
| <div style="width:140px">Option</div> | <div style="width:50px">Type</div> | <div style="width:80px">Default</div> | Description |
|
|
143
143
|
|---|---|---|---|
|
|
144
|
-
| `--from-style` | `str` | *required* | Docstring style to convert from. `google` or `
|
|
145
|
-
| `--to-style` | `str` | *required* | Docstring style to convert to. `google` or `
|
|
146
|
-
| `--line-length` | `int` | 100
|
|
147
|
-
| `--exclude` | `str` | —
|
|
148
|
-
| `--diff` | flag | —
|
|
144
|
+
| `--from-style` | `str` | *required* | Docstring style to convert from. `google`, `numpy` or `sphinx`. |
|
|
145
|
+
| `--to-style` | `str` | *required* | Docstring style to convert to. `google`, `numpy` or `sphinx`. Must differ from `--from-style`. |
|
|
146
|
+
| `--line-length` | `int` | 100 | Maximum number of characters allowed per line after formatting. |
|
|
147
|
+
| `--exclude` | `str` | — | A glob pattern for paths to exclude. Can be passed multiple times. Single-path patterns (e.g. `tests`, `*.pyi`) match by name anywhere in the tree. Relative patterns (e.g. `src/generated/*.py`) match against the path relative to the project root. |
|
|
148
|
+
| `--diff` | flag | — | Print a unified diff of changes to stdout instead of modifying files. No files are written when this flag is set. |
|
|
149
149
|
|
|
150
150
|
`--from-style` and `--to-style` have no config-file or default fallback — both must be given explicitly on every `convert` invocation, and must be different from each other.
|
|
151
151
|
|
|
@@ -375,6 +375,47 @@ def example_function(example_argument_1: str, example_argument_2: int) -> str:
|
|
|
375
375
|
- In the `Examples` section, start the Python REPL with `>>>` and use `...` for continuation lines, matching Pydoc conventions — same as Google style.
|
|
376
376
|
- These same section keywords can also be used in module or class docstrings — for example, a `Parameters` section in a class docstring, or an `Examples` section in a module docstring.
|
|
377
377
|
|
|
378
|
+
**Sphinx / reST**
|
|
379
|
+
|
|
380
|
+
```python
|
|
381
|
+
def example_function(example_argument_1: str, example_argument_2: int) -> str:
|
|
382
|
+
"""Demonstrates a Sphinx-style function docstring with multiple
|
|
383
|
+
sections.
|
|
384
|
+
|
|
385
|
+
This function exists purely as a formatting example and
|
|
386
|
+
illustrates how parameters, return values, and raised exceptions
|
|
387
|
+
are documented using reStructuredText info fields.
|
|
388
|
+
|
|
389
|
+
:param example_argument_1: First example input value used to
|
|
390
|
+
construct a formatted result string.
|
|
391
|
+
:type example_argument_1: str
|
|
392
|
+
:param example_argument_2: Second example input value used to
|
|
393
|
+
influence the transformation logic.
|
|
394
|
+
:type example_argument_2: int
|
|
395
|
+
:returns: A formatted string combining both input arguments into a
|
|
396
|
+
single human-readable representation.
|
|
397
|
+
:rtype: str
|
|
398
|
+
:raises ValueError: Raised when example_argument_2 is negative or
|
|
399
|
+
zero, as only positive integers are considered valid in this
|
|
400
|
+
demonstration.
|
|
401
|
+
|
|
402
|
+
.. note::
|
|
403
|
+
Additional informational directives such as ``.. note::`` and
|
|
404
|
+
``.. warning::`` are recognized and preserved during
|
|
405
|
+
formatting.
|
|
406
|
+
"""
|
|
407
|
+
if example_argument_2 <= 0:
|
|
408
|
+
raise ValueError("example_argument_2 must be positive")
|
|
409
|
+
|
|
410
|
+
return f"{example_argument_1}-{example_argument_2}"
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
- Parameters are documented with `:param name: description` info fields, and their types with a separate `:type name: type` field. An inline form (`:param str name: description`) is also accepted on input and is split into the two-field form on output.
|
|
414
|
+
- Types are genuinely optional in reST: a `:param:` without a matching `:type:` is preserved as-is, and `docstring_tailor` never fabricates a type when one is absent.
|
|
415
|
+
- Return values use `:returns:` (with `:return:` accepted as an alias), and the return type uses `:rtype:`.
|
|
416
|
+
- Raised exceptions use `:raises Exception: description` (`:raise`, `:except` and `:exception` are accepted as aliases).
|
|
417
|
+
- Informational directives such as `.. note::`, `.. warning::`, `.. seealso::` and `.. example::` are recognized and their indented bodies are formatted while the directive header is preserved.
|
|
418
|
+
|
|
378
419
|
### Codeblocks
|
|
379
420
|
|
|
380
421
|
**Google / Numpy** (identical for this example)
|
|
@@ -523,7 +564,11 @@ Steps:
|
|
|
523
564
|
|
|
524
565
|
### 60 characters per line — The Minimalist Monk 🧘
|
|
525
566
|
|
|
526
|
-
You believe every character has a purpose and every extra column is a personal failure 😤. You keep your docstrings short, your functions tiny, and your emotional attachment to whitespace surprisingly strong.
|
|
567
|
+
You believe every character has a purpose and every extra column is a personal failure 😤. You keep your docstrings short, your functions tiny, and your emotional attachment to whitespace surprisingly strong. Variable names? Anything longer than two characters is wasteful bloat — x, y, z, and i are sufficient for any problem. Docstrings are memory theft; everything the code needs to say should be obvious from context or inferred through pure spiritual understanding 🙏. Why document when you could just make the code so minimalist that it transcends the need for explanation? Your motto: if it takes more than 60 characters to explain, the explanation itself is the bug, not the code.
|
|
568
|
+
|
|
569
|
+
### 79 characters per line — The Precision Tuner ⚙️
|
|
570
|
+
|
|
571
|
+
You didn't choose 79 characters; you derived it through first principles and a spreadsheet. You read every formatter's GitHub issues, every style guide's rationale, and you have strong opinions about why 80 is overrated but 78 is cowardice 😤. You've A/B tested readability on three different monitors, measured your own eye-tracking data, and lost sleep over whether \n counts toward the limit or not. You configure your linter to lint your linter, and you have a .editorconfig file that is longer than most people's actual code 📋. You know exactly why PEP 8 suggested 79 and you've defended this choice at dinner parties with the fervor of someone protecting their firstborn child 🛡️. You don't just use docstring_tailor; you've benchmarked it against seven alternatives and created a spreadsheet ranking their consistency. Your line length is not a preference—it's a thesis 📊. You sleep well knowing that you have optimized, and the universe is in perfect order, exactly 79 characters wide.
|
|
527
572
|
|
|
528
573
|
### 80 characters per line — The Digital Archaeologist 🦖
|
|
529
574
|
|
|
@@ -552,6 +597,8 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
552
597
|
| <div style="width:70px">Resource</div> | <div style="width:100px">Description</div> | <div style="width:130px">Link</div>
|
|
553
598
|
|---|---|---|
|
|
554
599
|
| PEP 257 - Docstring Conventions | Documents the semantics and conventions associated with Python docstrings. | [Link](https://peps.python.org/pep-0257/) |
|
|
600
|
+
| PEP 287 - reStructuredText Docstring Format | Specifies a reStructuredText-based markup convention for Python docstrings, the basis of the Sphinx/reST style. | [Link](https://peps.python.org/pep-0287) |
|
|
601
|
+
| PEP 484 - Type Hints | Provides a standard syntax for type annotations in Python. | [Link](https://peps.python.org/pep-0484/) |
|
|
555
602
|
| Google Python Style Guide | Lists *dos and don'ts* for Python programs. | [Link](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings) |
|
|
556
603
|
| Numpy Style Guide | Describes the syntax and best practices for docstrings used with the numpydoc extension for Sphinx | [Link](https://numpydoc.readthedocs.io/en/latest/format.html) |
|
|
557
604
|
| Types of indentation | Wikipedia article that defines different kinds of indentation | [Link](https://en.wikipedia.org/wiki/Indentation_(typesetting)) |
|
|
@@ -572,6 +619,8 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
572
619
|
| `0.2.0` | 2026-06-07 | Feature update | <ul><li>Implemented the `detect-lists` parameter, adding support for unordered and ordered (numbered) lists in docstrings. When enabled, list structures are detected automatically and each list item is formatted onto its own line.</li><li>Introduced a declarative golden-file test framework for formatter validation. Test cases are now generated from parametrized templates using Cartesian-product expansion, significantly reducing boilerplate and improving scalability for configuration coverage.</li><li>Expanded this `README.md` with the 'API Overview', 'Release Notes', 'Example docstrings' and 'Roadmap' sections.</li><li>Test coverage: 75%</li></ul> |
|
|
573
620
|
| `0.2.1` | 2026-06-11 | Feature update | <ul><li>Added the `-V`/`--version` command to the CLI.</li><li>Added the `--exclude` command to the CLI.</li><li>Added the `--diff` command to the CLI.</li><li>Added the 'Demo' part to to the `README.md`.</ul> |
|
|
574
621
|
| `0.3.0` | 2026-07-20 | Feature update & bug fixes | <ul><li>Introduced a style-agnostic intermediate representation (IR) model and refactored parsing into an abstract base class hierarchy. Google and NumPy docstrings now parse into the same IR via `IndentationBasedParser` subclasses, enabling lossless conversion between styles. Structured list parsing is delegated to style-specific implementations to handle syntactic differences (Google's inline `name (type):` vs. NumPy's `name : type` on separate lines).</li><li>Refactored rendering to match the parser architecture: `DocstringRendererBase` (ABC) with style-specific subclasses that implement two hooks — section header formatting (Google's `Args:` vs. NumPy's `Parameters` + underline) and section body indentation rules (confirmed against numpy's own docstrings to keep bodies flush with headers, unlike Google). Keyword translation between styles happens automatically during conversion.</li><li>Code sections and Python REPL blocks now also can be created outside the 'Example(s)' section.</li><li>Fixed a bug when codeblock sections contain blank lines.</li><li>Fixed a bug when the docstring starts immediately with an (un)ordered list.</li><li>Removed `detect-lists` as CLI parameter, because the logic should always be applied if the docstring contains (un)ordered lists.</li><li>Changed behaviour for empty docstrings so that it consistent with Ruff.</li></ul> |
|
|
622
|
+
| `0.3.1` | 2026-07-21 | Small fixes | <ul><li>The `style` parameter does not have a default argument anymore, instead it always has to be configured explicitly by the user.</li><li>Fixed a bug where one-line docstrings inside indented scopes (e.g. class or method bodies) were wrapped to multiple lines prematurely, due to indentation being counted twice when checking against the configured line length.</li> <li>Added an exception, consistent with Ruff, allowing a one-line docstring to exceed the configured line length by up to 3 characters when only the closing triple quotes would otherwise be pushed onto their own line. This prevents docstring_tailor and Ruff from repeatedly reformatting the same docstring back and forth when both are run as pre-commit hooks.</li></ul> |
|
|
623
|
+
| `0.4.0` | 2026-07-24 | Feature update | <ul><li>Added support for the Sphinx/reST docstring `style`, covering both parsing and rendering. Sphinx docstrings now parse into the same style-agnostic intermediate representation (IR) as Google and NumPy, enabling lossless conversion in all directions between the three styles (`format --style sphinx` and `convert` to/from `sphinx`).</li><li>Extracted a shared `DocstringParserBase` holding the style-agnostic flat-content pipeline; `IndentationBasedParser` (Google/NumPy) and the new directive-based `SphinxDocstringParser` both build on it, reusing the existing pipeline rather than duplicating logic.</li><li>The Sphinx parser handles info-field lists (`:param:`/`:type:`, `:returns:`/`:rtype:`, `:raises:`), the inline parameter form (`:param str name:`), field/type pairing by name, tag aliases (`:return:`, `:raise:`, `:except:`, `:exception:`), and informational directives (`.. note::`, `.. warning::`, `.. seealso::`, `.. example::`).</li><li>The Sphinx renderer emits a contiguous info-field list with separate `:type:`/`:rtype:` lines, with hanging-indent wrapping of field bodies.</li><li>Modelled an absent parameter type as `None` in the IR (never fabricated), and updated the Google and NumPy renderers to degrade gracefully when a type is undocumented.</li><li>Reorganized the golden-file test fixtures into per-style folders (`google/`, `sphinx/`, `convert/`), with the fixture style folder derived automatically from each test case's configuration.</li></ul> |
|
|
575
624
|
|
|
576
625
|
## Roadmap
|
|
577
626
|
|
|
@@ -589,6 +638,15 @@ You don't wrap text because wrapping is a skill issue. You let photons travel un
|
|
|
589
638
|
- Formatting module for the remaining docstring formats (Sphinx, Epydoc), driven
|
|
590
639
|
entirely by the same IR already used for Google and NumPy.
|
|
591
640
|
|
|
641
|
+
### Finish the Sphinx/reST implementation
|
|
642
|
+
|
|
643
|
+
The core Sphinx style (parameters, returns, raises, and the common admonitions) is supported, but full coverage of every Sphinx construct is not there yet. Currently, unrecognized constructs are passed through as plain paragraph text — never dropped, but not parsed into a structured section, so they don't wrap as fields and don't convert to a Google/NumPy equivalent. The following would close that gap:
|
|
644
|
+
|
|
645
|
+
- Class attribute fields (`:ivar:`, `:cvar:`, `:var:` paired with `:vartype:`), mapped onto the same `Attributes` section Google and NumPy already expose, so class docstrings round-trip and convert like the other styles. Requires a new field-pairing path in the parser, an `Attributes` render path in the renderer, and a fix to the keyword translation tables (which currently fold Attributes into Parameters).
|
|
646
|
+
- Keyword-only argument fields (`:keyword:` / `:kwarg:` with `:kwtype:`), aliased onto the existing parameter/type handling.
|
|
647
|
+
- The broader set of admonition directives (`.. tip::`, `.. important::`, `.. caution::`, `.. attention::`, `.. hint::`, `.. danger::`, `.. error::`, `.. todo::`, `.. deprecated::`, `.. versionadded::`, `.. versionchanged::`), added to the directive-to-header map so their bodies format as named paragraphs. Headers without a Google/NumPy equivalent pass through unchanged on conversion.
|
|
648
|
+
- Literal-body directives (`.. code-block::`, `.. math::`) — more involved, because their content must be preserved verbatim and never reflowed, and there is no clean equivalent in the current IR. Needs a dedicated literal-block IR node before it can be handled safely.
|
|
649
|
+
|
|
592
650
|
### Nice to have
|
|
593
651
|
- Make sure the package can be used as a pre-commit hook.
|
|
594
652
|
- LSP (Language Server Protocol) support, enabling real-time feedback on malformed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "docstring-tailor"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
description = "Formats Python docstrings to PEP 257 style with configurable line length."
|
|
5
5
|
authors = [{ name = "Auke Bruinsma", email = "afbruinsma@gmail.com" }]
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -16,8 +16,7 @@ class DocstringStyle(str, Enum):
|
|
|
16
16
|
epydoc = "epydoc"
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
SUPPORTED_STYLES = {DocstringStyle.google, DocstringStyle.numpy}
|
|
20
|
-
DEFAULT_STYLE = DocstringStyle.google
|
|
19
|
+
SUPPORTED_STYLES = {DocstringStyle.google, DocstringStyle.numpy, DocstringStyle.sphinx}
|
|
21
20
|
|
|
22
21
|
# Argument: '--line-length'
|
|
23
22
|
LINE_LENGTH_MIN: int = 30
|
|
@@ -21,6 +21,7 @@ RE_PATTERN_STRUCTURED_LIST_NAME_AND_TYPE = re.compile(
|
|
|
21
21
|
)
|
|
22
22
|
RE_PATTERN_NUMPY_SECTION_UNDERLINE = re.compile(r"^-+$")
|
|
23
23
|
|
|
24
|
+
|
|
24
25
|
# =========================================
|
|
25
26
|
# Constants used for all docstring formats.
|
|
26
27
|
# =========================================
|
|
@@ -69,7 +70,8 @@ PARAMETER_TYPE_ANNOTATION_CLOSE: str = ")"
|
|
|
69
70
|
# ============================================
|
|
70
71
|
|
|
71
72
|
|
|
72
|
-
# Google
|
|
73
|
+
# === Google ===
|
|
74
|
+
|
|
73
75
|
GOOGLE_NAMED_PARAGRAPH_SECTIONS = frozenset(
|
|
74
76
|
{
|
|
75
77
|
"Note",
|
|
@@ -91,8 +93,8 @@ GOOGLE_ALL_SECTION_KEYWORDS = (
|
|
|
91
93
|
GOOGLE_NAMED_PARAGRAPH_SECTIONS | GOOGLE_STRUCTURED_LIST_SECTIONS
|
|
92
94
|
)
|
|
93
95
|
|
|
96
|
+
# === NumPy ---
|
|
94
97
|
|
|
95
|
-
# NumPy
|
|
96
98
|
NUMPY_ITEM_SECTIONS = frozenset(
|
|
97
99
|
{"Attributes", "Methods", "Parameters", "Raises", "Receives", "Returns", "Yields"}
|
|
98
100
|
)
|
|
@@ -107,8 +109,58 @@ SPHINX_PLAIN_DIRECTIVES = frozenset(
|
|
|
107
109
|
)
|
|
108
110
|
SPHINX_DIRECTIVES = SPHINX_ITEM_DIRECTIVES | SPHINX_PLAIN_DIRECTIVES
|
|
109
111
|
|
|
112
|
+
# === Sphinx ===
|
|
113
|
+
|
|
114
|
+
# Sphinx field tags, grouped by the IR section they map to. Aliases (singular
|
|
115
|
+
# and plural spellings) are accepted on input; the renderer emits one canonical
|
|
116
|
+
# spelling per group. ':param' also accepts an inline type ':param <type>
|
|
117
|
+
# <name>:', handled by the parser.
|
|
118
|
+
SPHINX_PARAM_TAGS = frozenset({":parma", ":parameter", ":arg", ":argument"})
|
|
119
|
+
SPHINX_TYPE_TAGS = frozenset({":type"})
|
|
120
|
+
SPHINX_RETURN_TAGS = frozenset({":return", ":returns"})
|
|
121
|
+
SPHINX_RTYPE_TAGS = frozenset({":rtype"})
|
|
122
|
+
SPHINX_RAISE_TAGS = frozenset({":raise", ":raises", ":except", ":exception"})
|
|
123
|
+
|
|
124
|
+
# All field tags that open a structured-list entry (as opposed to type metadata
|
|
125
|
+
# for a preceding entry). Used to detect the start of a field-list block.
|
|
126
|
+
SPHINX_FIELD_TAGS = (
|
|
127
|
+
SPHINX_PARAM_TAGS
|
|
128
|
+
| SPHINX_TYPE_TAGS
|
|
129
|
+
| SPHINX_RETURN_TAGS
|
|
130
|
+
| SPHINX_RTYPE_TAGS
|
|
131
|
+
| SPHINX_RAISE_TAGS
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Canonical section keywords used for Sphinx StructuredList nodes in the IR, so
|
|
135
|
+
# keyword translation and rendering share one vocabulary.
|
|
136
|
+
SPHINX_KEYWORD_PARAMETERS: str = "Parameters"
|
|
137
|
+
SPHINX_KEYWORD_RETURNS: str = "Returns"
|
|
138
|
+
SPHINX_KEYWORD_RAISES: str = "Raises"
|
|
139
|
+
|
|
140
|
+
# Canonical Sphinx directive-to-header mapping for admonition sections rendered
|
|
141
|
+
# as NamedParagraph nodes.
|
|
142
|
+
SPHINX_DIRECTIVE_HEADERS: dict[str, str] = {
|
|
143
|
+
".. note::": "Note",
|
|
144
|
+
".. warning::": "Warning",
|
|
145
|
+
".. seealso::": "See Also",
|
|
146
|
+
".. example::": "Example",
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# Reverse mapping: canonical header to its Sphinx directive marker, for
|
|
150
|
+
# rendering NamedParagraph nodes back to reST directives.
|
|
151
|
+
SPHINX_HEADER_DIRECTIVES: dict[str, str] = {
|
|
152
|
+
header: directive for directive, header in SPHINX_DIRECTIVE_HEADERS.items()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
# Canonical Sphinx field-tag spellings emitted my the renderer.
|
|
156
|
+
SPHINX_RENDER_PARAM_TAG: str = ":param"
|
|
157
|
+
SPHINX_RENDER_TYPE_TAG: str = ":type"
|
|
158
|
+
SPHINX_RENDER_RETURNS_TAG: str = ":returns"
|
|
159
|
+
SPHINX_RENDER_RTYPE_TAG: str = ":rtype"
|
|
160
|
+
SPHINX_RENDER_RAISES_TAG: str = ":raises"
|
|
161
|
+
|
|
162
|
+
# === Epydoc ===
|
|
110
163
|
|
|
111
|
-
# Epydoc-style docstring tag markers.
|
|
112
164
|
EPYDOC_ITEM_TAGS = frozenset({"@param", "@raise", "@return", "@rtype", "@type"})
|
|
113
165
|
EPYDOC_PLAIN_TAGS = frozenset({"@note", "@warning"})
|
|
114
166
|
EPYDOC_TAGS = EPYDOC_ITEM_TAGS | EPYDOC_PLAIN_TAGS
|
|
@@ -62,12 +62,17 @@ class StructuredListParameter:
|
|
|
62
62
|
name (str | None): The variable or attribute name, or None when the
|
|
63
63
|
entry has no name -- the conventional shape for Returns and Yields
|
|
64
64
|
entries, which document only the type.
|
|
65
|
-
type (str): The annotated type of the variable
|
|
65
|
+
type (str | None): The annotated type of the variable, or None when no
|
|
66
|
+
type was documented. Types are optional in some styles (e.g.
|
|
67
|
+
Sphinx/reST field lists relying on PEP 484 signature hints), so
|
|
68
|
+
absence is modelled explicitly rather than as an empty string,
|
|
69
|
+
mirroring the name field. Renderers omit the type entirely when it
|
|
70
|
+
is None.
|
|
66
71
|
description (str): The description of the variable.
|
|
67
72
|
"""
|
|
68
73
|
|
|
69
74
|
name: str | None
|
|
70
|
-
type: str
|
|
75
|
+
type: str | None
|
|
71
76
|
description: str
|
|
72
77
|
|
|
73
78
|
|
|
@@ -16,7 +16,6 @@ import typer
|
|
|
16
16
|
|
|
17
17
|
from docstring_tailor.cli_config import (
|
|
18
18
|
DEFAULT_PATHS,
|
|
19
|
-
DEFAULT_STYLE,
|
|
20
19
|
LINE_LENGTH_DEFAULT,
|
|
21
20
|
LINE_LENGTH_MAX,
|
|
22
21
|
LINE_LENGTH_MIN,
|
|
@@ -198,9 +197,18 @@ def format_command(
|
|
|
198
197
|
resolved_paths, resolved_line_length, resolved_exclude, file_config = (
|
|
199
198
|
_resolve_common_options(paths=paths, line_length=line_length, exclude=exclude)
|
|
200
199
|
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
|
|
201
|
+
resolved_style = style or file_config.get("style")
|
|
202
|
+
|
|
203
|
+
if resolved_style is None:
|
|
204
|
+
typer.echo(
|
|
205
|
+
"Error: Docstring style not specified. "
|
|
206
|
+
"Pass --style on the command line or set 'style' in your config file "
|
|
207
|
+
"(pyproject.toml or docstring_tailor.toml)."
|
|
208
|
+
)
|
|
209
|
+
raise typer.Exit(code=1)
|
|
210
|
+
|
|
211
|
+
resolved_style = DocstringStyle(resolved_style)
|
|
204
212
|
|
|
205
213
|
_validate_supported_style(resolved_style)
|
|
206
214
|
|