format-docstring 0.1.9__tar.gz → 0.2.1__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.
- {format_docstring-0.1.9 → format_docstring-0.2.1}/.pre-commit-config.yaml +26 -4
- {format_docstring-0.1.9 → format_docstring-0.2.1}/AGENTS.md +49 -7
- {format_docstring-0.1.9 → format_docstring-0.2.1}/CHANGELOG.md +18 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/PKG-INFO +135 -10
- {format_docstring-0.1.9 → format_docstring-0.2.1}/README.md +134 -9
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/base_fixer.py +12 -2
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/docstring_rewriter.py +204 -10
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_google.py +5 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_numpy.py +288 -5
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_utils.py +14 -8
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/PKG-INFO +135 -10
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/SOURCES.txt +4 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/pyproject.toml +1 -1
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/fix_rst_backticks.txt +1 -1
- format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_dont_sync_raises.txt +48 -0
- format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_parameters.txt +197 -0
- format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_returns.txt +226 -0
- format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_yields.txt +103 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tox.ini +15 -25
- {format_docstring-0.1.9 → format_docstring-0.2.1}/.github/workflows/python-package.yml +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/.github/workflows/python-publish.yml +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/.gitignore +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/.pre-commit-hooks.yaml +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/LICENSE +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/__init__.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/config.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/main_jupyter.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/main_py.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/dependency_links.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/entry_points.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/requires.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/top_level.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/muff.toml +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/requirements.dev +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/setup.cfg +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/__init__.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/helpers.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_base_fixer.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_config.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/README.md +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/four_level_nested_classes.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/indent_misaligned_all.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/new_lines_before_and_after.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/no_format_docstring_comment.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/section_headings_with_colons.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/single_line_docstring.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after.ipynb +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after_50.ipynb +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after_50.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/before.ipynb +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/before.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/jupyter/before.ipynb +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/jupyter/verbose_before.ipynb +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/README.md +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/fix_rst_backticks.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/section_headings_with_colons.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/playground.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_docstring_rewriter.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_google.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_numpy.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_utils.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_main_jupyter.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_main_py.py +0 -0
- {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_playground.py +0 -0
|
@@ -5,12 +5,19 @@ repos:
|
|
|
5
5
|
hooks:
|
|
6
6
|
- id: trailing-whitespace
|
|
7
7
|
- id: end-of-file-fixer
|
|
8
|
+
exclude: \.json$|\.ipynb$
|
|
8
9
|
- id: debug-statements
|
|
9
10
|
- id: double-quote-string-fixer
|
|
10
11
|
- id: requirements-txt-fixer
|
|
11
|
-
- id: pretty-format-json
|
|
12
|
-
args: [--no-ensure-ascii, --indent=4, --no-sort-keys]
|
|
13
12
|
exclude: \.ipynb$
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
args: [--maxkb=1000]
|
|
15
|
+
- id: check-toml
|
|
16
|
+
- id: check-yaml
|
|
17
|
+
- id: name-tests-test
|
|
18
|
+
args: [--pytest-test-first]
|
|
19
|
+
exclude: ^tests/test_data/|^tests/helpers\.py$
|
|
20
|
+
- id: check-merge-conflict
|
|
14
21
|
- repo: https://github.com/asottile/pyupgrade
|
|
15
22
|
rev: v3.20.0
|
|
16
23
|
hooks:
|
|
@@ -31,15 +38,30 @@ repos:
|
|
|
31
38
|
hooks:
|
|
32
39
|
- id: yamlfix
|
|
33
40
|
- repo: https://github.com/hukkin/mdformat
|
|
34
|
-
rev: 0.
|
|
41
|
+
rev: 1.0.0
|
|
35
42
|
hooks:
|
|
36
43
|
- id: mdformat
|
|
37
44
|
args: [--wrap, '79', --number]
|
|
38
|
-
additional_dependencies: [mdformat-
|
|
45
|
+
additional_dependencies: [mdformat-gfm]
|
|
46
|
+
- repo: https://github.com/jsh9/format-json
|
|
47
|
+
rev: 0.1.2
|
|
48
|
+
hooks:
|
|
49
|
+
- id: format-json
|
|
50
|
+
args:
|
|
51
|
+
- --autofix
|
|
52
|
+
- --no-ensure-ascii
|
|
53
|
+
- --indent=4
|
|
54
|
+
- --no-sort-keys
|
|
55
|
+
- --no-eof-newline
|
|
39
56
|
- repo: https://github.com/jsh9/markdown-toc-creator
|
|
40
57
|
rev: 0.0.11
|
|
41
58
|
hooks:
|
|
42
59
|
- id: markdown-toc-creator
|
|
60
|
+
- repo: https://github.com/jsh9/markdown-heading-numbering
|
|
61
|
+
rev: 0.1.0
|
|
62
|
+
hooks:
|
|
63
|
+
- id: markdown-heading-numbering
|
|
64
|
+
exclude: ^CHANGELOG\.md$
|
|
43
65
|
- repo: local
|
|
44
66
|
hooks:
|
|
45
67
|
- id: format-docstring
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This guide briefs coding agents working on `format-docstring`. Use it to get
|
|
4
4
|
oriented before making changes.
|
|
5
5
|
|
|
6
|
-
## Quick Snapshot
|
|
6
|
+
## 1. Quick Snapshot
|
|
7
7
|
|
|
8
8
|
- Formats NumPy-style docstrings (with experimental Google support) in `.py`
|
|
9
9
|
files and Jupyter notebooks while preserving surrounding code.
|
|
@@ -13,7 +13,7 @@ oriented before making changes.
|
|
|
13
13
|
`jupyter-notebook-parser`, and `tomli/tomllib` for configuration loading.
|
|
14
14
|
- Version is sourced dynamically in `format_docstring/__init__.py`.
|
|
15
15
|
|
|
16
|
-
## Repository Layout
|
|
16
|
+
## 2. Repository Layout
|
|
17
17
|
|
|
18
18
|
- `format_docstring/main_py.py` – Click CLI for Python files; validates input
|
|
19
19
|
and delegates to `PythonFileFixer`.
|
|
@@ -33,13 +33,24 @@ oriented before making changes.
|
|
|
33
33
|
- `tests/` – Pytest suite with fixture-driven cases in `tests/test_data/`; see
|
|
34
34
|
`tests/helpers.py` for fixture loading helpers.
|
|
35
35
|
|
|
36
|
-
## Implementation Notes
|
|
36
|
+
## 3. Implementation Notes
|
|
37
37
|
|
|
38
38
|
- `docstring_rewriter.fix_src` parses with `ast.parse`, collects docstring
|
|
39
39
|
literals, and rewrites source slices using absolute offsets from
|
|
40
40
|
`calc_line_starts`; this avoids `ast.unparse` and keeps comments/spacing.
|
|
41
|
+
- For functions, `_collect_param_metadata` records signature annotations and
|
|
42
|
+
default values so NumPy `Parameters` signatures in docstrings are
|
|
43
|
+
resynchronised with the real function definition. Defaulted parameters omit
|
|
44
|
+
redundant `, optional`, and forward references keep their original quoting.
|
|
45
|
+
- Return annotations are likewise projected into `Returns`/`Yields` sections,
|
|
46
|
+
mirroring tuple element splits when the docstring already enumerates them.
|
|
47
|
+
- `Raises` section entries are treated like signature lines in the NumPy
|
|
48
|
+
wrapper so exception names stay untouched while descriptions wrap.
|
|
41
49
|
- Wrapping honors NumPy section heuristics, rST constructs, code fences,
|
|
42
50
|
`Examples` prompts, and literal blocks introduced by `::`.
|
|
51
|
+
- `_normalize_signature_segment` flattens multiline annotations via
|
|
52
|
+
`ast.unparse` but uses token-level replay to preserve the author's quoting
|
|
53
|
+
style for forward references and string defaults.
|
|
43
54
|
- CLI exposes `--docstring-style`, but the Python entry-point currently raises
|
|
44
55
|
if a non-NumPy style is requested; Jupyter flow passes style through
|
|
45
56
|
unchanged.
|
|
@@ -48,7 +59,7 @@ oriented before making changes.
|
|
|
48
59
|
- Notebook fixer round-trips JSON via `json.dump(..., indent=1)` and rewrites
|
|
49
60
|
cells only when content changes, preserving magics with `reconstruct_source`.
|
|
50
61
|
|
|
51
|
-
## Configuration
|
|
62
|
+
## 4. Configuration
|
|
52
63
|
|
|
53
64
|
- User-facing configuration lives under `[tool.format_docstring]` inside
|
|
54
65
|
`pyproject.toml` and supports `line_length`, `docstring_style`, `exclude`,
|
|
@@ -59,7 +70,7 @@ oriented before making changes.
|
|
|
59
70
|
- Default exclude pattern is `\.git|\.tox|\.pytest_cache`; tests tweak it as
|
|
60
71
|
needed.
|
|
61
72
|
|
|
62
|
-
## Development Workflow
|
|
73
|
+
## 5. Development Workflow
|
|
63
74
|
|
|
64
75
|
- Install: `pip install -e .` for the project,
|
|
65
76
|
`pip install -r requirements.dev` for tooling.
|
|
@@ -74,20 +85,51 @@ oriented before making changes.
|
|
|
74
85
|
`format-docstring-jupyter --help`.
|
|
75
86
|
- Pre-commit: `pre-commit run -a`.
|
|
76
87
|
|
|
77
|
-
## Testing Notes
|
|
88
|
+
## 6. Testing Notes
|
|
78
89
|
|
|
79
90
|
- Fixture files under `tests/test_data/line_wrap` and
|
|
80
91
|
`tests/test_data/end_to_end` use `LINE_LENGTH: <int>` headers followed by
|
|
81
92
|
`BEFORE`/`AFTER` sections split by `**********`.
|
|
93
|
+
- Regression fixture
|
|
94
|
+
`tests/test_data/end_to_end/numpy/signature_dont_sync_raises.txt` guards
|
|
95
|
+
against mutating exception names in `Raises` blocks.
|
|
82
96
|
- `tests/test_playground.py` focuses on regression snippets;
|
|
83
97
|
`tests/test_config.py` exercises config discovery and CLI overrides.
|
|
84
98
|
- When modifying wrapping rules, update both the helper (`line_wrap_utils.py`)
|
|
85
99
|
and the corresponding expectation files in `tests/test_data/`.
|
|
86
100
|
|
|
87
|
-
## Style Guidance
|
|
101
|
+
## 7. Style Guidance
|
|
88
102
|
|
|
89
103
|
- Formatting rules mirror `muff.toml` (line length 79, single quotes, NumPy
|
|
90
104
|
docstring convention). Respect these when adding code.
|
|
91
105
|
- Keep docstring style tests conservative: avoid mutating non-docstring
|
|
92
106
|
content, and add regression cases whenever handling around literal sections
|
|
93
107
|
or tables changes.
|
|
108
|
+
|
|
109
|
+
## 8. What is a "signature line"?
|
|
110
|
+
|
|
111
|
+
They are the lines in the docstring where input and return args are defined,
|
|
112
|
+
for example, in this docstring:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
"""
|
|
116
|
+
Do something
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
arg1 : str
|
|
121
|
+
Arg 1
|
|
122
|
+
arg2 : int = 2
|
|
123
|
+
Arg 2
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
dict[str, str]
|
|
128
|
+
The mapping
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Signature lines are:
|
|
132
|
+
|
|
133
|
+
- arg1 : str
|
|
134
|
+
- arg2 : int = 2
|
|
135
|
+
- dict[str, str]
|
|
@@ -6,6 +6,22 @@ The format is based on
|
|
|
6
6
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
7
7
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## [0.2.1] - 2025-10-20
|
|
10
|
+
|
|
11
|
+
- Fixed
|
|
12
|
+
- A bug where raised exceptions in docstrings are incorrectly changed
|
|
13
|
+
- Full diff
|
|
14
|
+
- https://github.com/jsh9/format-docstring/compare/0.2.0...0.2.1
|
|
15
|
+
|
|
16
|
+
## [0.2.0] - 2025-10-20
|
|
17
|
+
|
|
18
|
+
- Added
|
|
19
|
+
- AST-driven synchronization of NumPy `Parameters` and `Returns` signature
|
|
20
|
+
lines with the function signature, including tuple element expansion for
|
|
21
|
+
multi-line return blocks
|
|
22
|
+
- Full diff
|
|
23
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.9...0.2.0
|
|
24
|
+
|
|
9
25
|
## [0.1.9] - 2025-10-16
|
|
10
26
|
|
|
11
27
|
- Added
|
|
@@ -17,6 +33,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
17
33
|
- Changed
|
|
18
34
|
- Added "self format" pre-commit hook to format docstrings within this repo
|
|
19
35
|
with its own formatting logic
|
|
36
|
+
- Full diff
|
|
37
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.8...0.1.9
|
|
20
38
|
|
|
21
39
|
## [0.1.8] - 2025-10-14
|
|
22
40
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: format-docstring
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A Python formatter to wrap/adjust docstring lines
|
|
5
5
|
Author-email: jsh9 <25124332+jsh9@users.noreply.github.com>
|
|
6
6
|
Maintainer-email: jsh9 <25124332+jsh9@users.noreply.github.com>
|
|
@@ -34,6 +34,8 @@ Dynamic: license-file
|
|
|
34
34
|
|
|
35
35
|
A Python formatter to automatically format numpy-style docstrings.
|
|
36
36
|
|
|
37
|
+
______________________________________________________________________
|
|
38
|
+
|
|
37
39
|
**Table of Contents:**
|
|
38
40
|
|
|
39
41
|
<!--TOC-->
|
|
@@ -45,6 +47,7 @@ A Python formatter to automatically format numpy-style docstrings.
|
|
|
45
47
|
- [2.3. Minor typos can be automatically fixed](#23-minor-typos-can-be-automatically-fixed)
|
|
46
48
|
- [2.4. Default value declarations are standardized](#24-default-value-declarations-are-standardized)
|
|
47
49
|
- [2.5. Single backticks are converted to double backticks (rST syntax)](#25-single-backticks-are-converted-to-double-backticks-rst-syntax)
|
|
50
|
+
- [2.6. Docstring parameters and returns stay in sync with signatures](#26-docstring-parameters-and-returns-stay-in-sync-with-signatures)
|
|
48
51
|
- [3. Installation](#3-installation)
|
|
49
52
|
- [4. Usage](#4-usage)
|
|
50
53
|
- [4.1. Command Line Interface](#41-command-line-interface)
|
|
@@ -54,24 +57,28 @@ A Python formatter to automatically format numpy-style docstrings.
|
|
|
54
57
|
- [5.1. Command-Line Options](#51-command-line-options)
|
|
55
58
|
- [5.2. Usage Examples](#52-usage-examples)
|
|
56
59
|
- [5.3. `pyproject.toml` Configuration](#53-pyprojecttoml-configuration)
|
|
60
|
+
- [6. Caveat](#6-caveat)
|
|
57
61
|
|
|
58
62
|
<!--TOC-->
|
|
59
63
|
|
|
64
|
+
______________________________________________________________________
|
|
65
|
+
|
|
60
66
|
## 1. Overview
|
|
61
67
|
|
|
62
68
|
`format-docstring` is a tool that automatically formats and wraps docstring
|
|
63
69
|
content in Python files and Jupyter notebooks.
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
Baseline reflow corresponds to the common docstring cleanups offered by
|
|
72
|
+
general-purpose formatters: splitting one-line docstrings into the canonical
|
|
73
|
+
multi-line layout (triple quotes, blank line, summary), normalizing
|
|
74
|
+
indentation, and wrapping text at a fixed column width without applying extra
|
|
75
|
+
heuristics.
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
| Feature | `format-docstring` | [docformatter] | [pydocstringformatter] | [Ruff] | [Black] |
|
|
78
|
+
| ----------------------------------------- | ------------------ | -------------- | ---------------------- | ------ | ------- |
|
|
79
|
+
| Docstring wrapping | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
80
|
+
| Compatible with line length linter (E501) | ✅ | ❌ | ❌ | N/A | N/A |
|
|
81
|
+
| Fixes common docstring typos | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
75
82
|
|
|
76
83
|
## 2. Before vs After Examples
|
|
77
84
|
|
|
@@ -187,6 +194,25 @@ def mu_function():
|
|
|
187
194
|
pass
|
|
188
195
|
```
|
|
189
196
|
|
|
197
|
+
or, Google-style section headers can be fixed:
|
|
198
|
+
|
|
199
|
+
```diff
|
|
200
|
+
def my_function():
|
|
201
|
+
"""
|
|
202
|
+
My function
|
|
203
|
+
|
|
204
|
+
- Args:
|
|
205
|
+
- ----
|
|
206
|
+
+ Parameters
|
|
207
|
+
+ ----------
|
|
208
|
+
arg1 : str
|
|
209
|
+
Arg 1
|
|
210
|
+
|
|
211
|
+
...
|
|
212
|
+
"""
|
|
213
|
+
pass
|
|
214
|
+
```
|
|
215
|
+
|
|
190
216
|
### 2.4. Default value declarations are standardized
|
|
191
217
|
|
|
192
218
|
```diff
|
|
@@ -230,9 +256,94 @@ def process_data(data):
|
|
|
230
256
|
- Processed data with key `result`.
|
|
231
257
|
+ Processed data with key ``result``.
|
|
232
258
|
"""
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 2.6. Docstring parameters and returns stay in sync with signatures
|
|
262
|
+
|
|
263
|
+
```diff
|
|
264
|
+
from typing import List, Optional
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def create_user(
|
|
268
|
+
user: Optional[str] = None,
|
|
269
|
+
roles: List["Role"] | None = None,
|
|
270
|
+
retries: int = 0,
|
|
271
|
+
serializer: "Serializer" | None = None,
|
|
272
|
+
something_else: tuple[int, ...] = (
|
|
273
|
+
"1",
|
|
274
|
+
'2',
|
|
275
|
+
3,
|
|
276
|
+
4,
|
|
277
|
+
5,
|
|
278
|
+
6,
|
|
279
|
+
7,
|
|
280
|
+
8,
|
|
281
|
+
9,
|
|
282
|
+
10,
|
|
283
|
+
11,
|
|
284
|
+
12,
|
|
285
|
+
),
|
|
286
|
+
) -> None:
|
|
287
|
+
"""
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
- user : str
|
|
291
|
+
+ user : Optional[str], default=None
|
|
292
|
+
Login name.
|
|
293
|
+
- roles : list
|
|
294
|
+
+ roles : List["Role"] | None, default=None
|
|
295
|
+
Assigned roles.
|
|
296
|
+
- retries : int
|
|
297
|
+
+ retries : int, default=0
|
|
298
|
+
Number of retry attempts.
|
|
299
|
+
- serializer : Serializer, optional
|
|
300
|
+
+ serializer : "Serializer" | None, default=None
|
|
301
|
+
Custom serializer instance.
|
|
302
|
+
- something_else : tuple[int, ...]
|
|
303
|
+
+ something_else : tuple[int, ...], default=("1", '2', 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
|
|
304
|
+
"""
|
|
233
305
|
pass
|
|
234
306
|
```
|
|
235
307
|
|
|
308
|
+
And return type hint:
|
|
309
|
+
|
|
310
|
+
```diff
|
|
311
|
+
def build_mapping() -> dict[str, str]:
|
|
312
|
+
"""
|
|
313
|
+
Returns
|
|
314
|
+
-------
|
|
315
|
+
- str
|
|
316
|
+
+ dict[str, str]
|
|
317
|
+
Mapping of values.
|
|
318
|
+
"""
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
For tuple return annotations, tuple elements are split across multiple
|
|
322
|
+
signature lines only when the docstring already adopted that layout:
|
|
323
|
+
|
|
324
|
+
```diff
|
|
325
|
+
def compute_values() -> tuple[int, str, list[str]]:
|
|
326
|
+
"""
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
- float
|
|
330
|
+
+ int
|
|
331
|
+
First element.
|
|
332
|
+
- str
|
|
333
|
+
+ str
|
|
334
|
+
Second element.
|
|
335
|
+
- List[str]
|
|
336
|
+
+ list[str]
|
|
337
|
+
Third element.
|
|
338
|
+
"""
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Annotations and defaults are extracted from the actual function signature, so
|
|
342
|
+
docstring signature lines reflect the ground truth. Defaulted parameters omit
|
|
343
|
+
redundant `, optional`, forward references keep their original quoting, and
|
|
344
|
+
return signatures track tuple splitting conventions already present in the
|
|
345
|
+
docstring.
|
|
346
|
+
|
|
236
347
|
## 3. Installation
|
|
237
348
|
|
|
238
349
|
```bash
|
|
@@ -367,3 +478,17 @@ verbose = "default" # or "diff" to print unified diffs
|
|
|
367
478
|
|
|
368
479
|
The tool searches for `pyproject.toml` starting from the target file/directory
|
|
369
480
|
and walking up the parent directories until one is found.
|
|
481
|
+
|
|
482
|
+
## 6. Caveat
|
|
483
|
+
|
|
484
|
+
This tool assumes the docstrings are written in **mostly** the correct format,
|
|
485
|
+
because it needs those formatting cues (such as section headers and `------`)
|
|
486
|
+
to parse docstrings.
|
|
487
|
+
|
|
488
|
+
If the docstrings are far from perfectly formatted, it's recommended that you
|
|
489
|
+
use AI coding assistants to rewrite the docstrings first.
|
|
490
|
+
|
|
491
|
+
[black]: https://github.com/psf/black
|
|
492
|
+
[docformatter]: https://github.com/PyCQA/docformatter
|
|
493
|
+
[pydocstringformatter]: https://github.com/DanielNoord/pydocstringformatter
|
|
494
|
+
[ruff]: https://github.com/astral-sh/ruff
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A Python formatter to automatically format numpy-style docstrings.
|
|
4
4
|
|
|
5
|
+
______________________________________________________________________
|
|
6
|
+
|
|
5
7
|
**Table of Contents:**
|
|
6
8
|
|
|
7
9
|
<!--TOC-->
|
|
@@ -13,6 +15,7 @@ A Python formatter to automatically format numpy-style docstrings.
|
|
|
13
15
|
- [2.3. Minor typos can be automatically fixed](#23-minor-typos-can-be-automatically-fixed)
|
|
14
16
|
- [2.4. Default value declarations are standardized](#24-default-value-declarations-are-standardized)
|
|
15
17
|
- [2.5. Single backticks are converted to double backticks (rST syntax)](#25-single-backticks-are-converted-to-double-backticks-rst-syntax)
|
|
18
|
+
- [2.6. Docstring parameters and returns stay in sync with signatures](#26-docstring-parameters-and-returns-stay-in-sync-with-signatures)
|
|
16
19
|
- [3. Installation](#3-installation)
|
|
17
20
|
- [4. Usage](#4-usage)
|
|
18
21
|
- [4.1. Command Line Interface](#41-command-line-interface)
|
|
@@ -22,24 +25,28 @@ A Python formatter to automatically format numpy-style docstrings.
|
|
|
22
25
|
- [5.1. Command-Line Options](#51-command-line-options)
|
|
23
26
|
- [5.2. Usage Examples](#52-usage-examples)
|
|
24
27
|
- [5.3. `pyproject.toml` Configuration](#53-pyprojecttoml-configuration)
|
|
28
|
+
- [6. Caveat](#6-caveat)
|
|
25
29
|
|
|
26
30
|
<!--TOC-->
|
|
27
31
|
|
|
32
|
+
______________________________________________________________________
|
|
33
|
+
|
|
28
34
|
## 1. Overview
|
|
29
35
|
|
|
30
36
|
`format-docstring` is a tool that automatically formats and wraps docstring
|
|
31
37
|
content in Python files and Jupyter notebooks.
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
Baseline reflow corresponds to the common docstring cleanups offered by
|
|
40
|
+
general-purpose formatters: splitting one-line docstrings into the canonical
|
|
41
|
+
multi-line layout (triple quotes, blank line, summary), normalizing
|
|
42
|
+
indentation, and wrapping text at a fixed column width without applying extra
|
|
43
|
+
heuristics.
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
| Feature | `format-docstring` | [docformatter] | [pydocstringformatter] | [Ruff] | [Black] |
|
|
46
|
+
| ----------------------------------------- | ------------------ | -------------- | ---------------------- | ------ | ------- |
|
|
47
|
+
| Docstring wrapping | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
48
|
+
| Compatible with line length linter (E501) | ✅ | ❌ | ❌ | N/A | N/A |
|
|
49
|
+
| Fixes common docstring typos | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
43
50
|
|
|
44
51
|
## 2. Before vs After Examples
|
|
45
52
|
|
|
@@ -155,6 +162,25 @@ def mu_function():
|
|
|
155
162
|
pass
|
|
156
163
|
```
|
|
157
164
|
|
|
165
|
+
or, Google-style section headers can be fixed:
|
|
166
|
+
|
|
167
|
+
```diff
|
|
168
|
+
def my_function():
|
|
169
|
+
"""
|
|
170
|
+
My function
|
|
171
|
+
|
|
172
|
+
- Args:
|
|
173
|
+
- ----
|
|
174
|
+
+ Parameters
|
|
175
|
+
+ ----------
|
|
176
|
+
arg1 : str
|
|
177
|
+
Arg 1
|
|
178
|
+
|
|
179
|
+
...
|
|
180
|
+
"""
|
|
181
|
+
pass
|
|
182
|
+
```
|
|
183
|
+
|
|
158
184
|
### 2.4. Default value declarations are standardized
|
|
159
185
|
|
|
160
186
|
```diff
|
|
@@ -198,9 +224,94 @@ def process_data(data):
|
|
|
198
224
|
- Processed data with key `result`.
|
|
199
225
|
+ Processed data with key ``result``.
|
|
200
226
|
"""
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 2.6. Docstring parameters and returns stay in sync with signatures
|
|
230
|
+
|
|
231
|
+
```diff
|
|
232
|
+
from typing import List, Optional
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def create_user(
|
|
236
|
+
user: Optional[str] = None,
|
|
237
|
+
roles: List["Role"] | None = None,
|
|
238
|
+
retries: int = 0,
|
|
239
|
+
serializer: "Serializer" | None = None,
|
|
240
|
+
something_else: tuple[int, ...] = (
|
|
241
|
+
"1",
|
|
242
|
+
'2',
|
|
243
|
+
3,
|
|
244
|
+
4,
|
|
245
|
+
5,
|
|
246
|
+
6,
|
|
247
|
+
7,
|
|
248
|
+
8,
|
|
249
|
+
9,
|
|
250
|
+
10,
|
|
251
|
+
11,
|
|
252
|
+
12,
|
|
253
|
+
),
|
|
254
|
+
) -> None:
|
|
255
|
+
"""
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
- user : str
|
|
259
|
+
+ user : Optional[str], default=None
|
|
260
|
+
Login name.
|
|
261
|
+
- roles : list
|
|
262
|
+
+ roles : List["Role"] | None, default=None
|
|
263
|
+
Assigned roles.
|
|
264
|
+
- retries : int
|
|
265
|
+
+ retries : int, default=0
|
|
266
|
+
Number of retry attempts.
|
|
267
|
+
- serializer : Serializer, optional
|
|
268
|
+
+ serializer : "Serializer" | None, default=None
|
|
269
|
+
Custom serializer instance.
|
|
270
|
+
- something_else : tuple[int, ...]
|
|
271
|
+
+ something_else : tuple[int, ...], default=("1", '2', 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
|
|
272
|
+
"""
|
|
201
273
|
pass
|
|
202
274
|
```
|
|
203
275
|
|
|
276
|
+
And return type hint:
|
|
277
|
+
|
|
278
|
+
```diff
|
|
279
|
+
def build_mapping() -> dict[str, str]:
|
|
280
|
+
"""
|
|
281
|
+
Returns
|
|
282
|
+
-------
|
|
283
|
+
- str
|
|
284
|
+
+ dict[str, str]
|
|
285
|
+
Mapping of values.
|
|
286
|
+
"""
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
For tuple return annotations, tuple elements are split across multiple
|
|
290
|
+
signature lines only when the docstring already adopted that layout:
|
|
291
|
+
|
|
292
|
+
```diff
|
|
293
|
+
def compute_values() -> tuple[int, str, list[str]]:
|
|
294
|
+
"""
|
|
295
|
+
Returns
|
|
296
|
+
-------
|
|
297
|
+
- float
|
|
298
|
+
+ int
|
|
299
|
+
First element.
|
|
300
|
+
- str
|
|
301
|
+
+ str
|
|
302
|
+
Second element.
|
|
303
|
+
- List[str]
|
|
304
|
+
+ list[str]
|
|
305
|
+
Third element.
|
|
306
|
+
"""
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Annotations and defaults are extracted from the actual function signature, so
|
|
310
|
+
docstring signature lines reflect the ground truth. Defaulted parameters omit
|
|
311
|
+
redundant `, optional`, forward references keep their original quoting, and
|
|
312
|
+
return signatures track tuple splitting conventions already present in the
|
|
313
|
+
docstring.
|
|
314
|
+
|
|
204
315
|
## 3. Installation
|
|
205
316
|
|
|
206
317
|
```bash
|
|
@@ -335,3 +446,17 @@ verbose = "default" # or "diff" to print unified diffs
|
|
|
335
446
|
|
|
336
447
|
The tool searches for `pyproject.toml` starting from the target file/directory
|
|
337
448
|
and walking up the parent directories until one is found.
|
|
449
|
+
|
|
450
|
+
## 6. Caveat
|
|
451
|
+
|
|
452
|
+
This tool assumes the docstrings are written in **mostly** the correct format,
|
|
453
|
+
because it needs those formatting cues (such as section headers and `------`)
|
|
454
|
+
to parse docstrings.
|
|
455
|
+
|
|
456
|
+
If the docstrings are far from perfectly formatted, it's recommended that you
|
|
457
|
+
use AI coding assistants to rewrite the docstrings first.
|
|
458
|
+
|
|
459
|
+
[black]: https://github.com/psf/black
|
|
460
|
+
[docformatter]: https://github.com/PyCQA/docformatter
|
|
461
|
+
[pydocstringformatter]: https://github.com/DanielNoord/pydocstringformatter
|
|
462
|
+
[ruff]: https://github.com/astral-sh/ruff
|
|
@@ -8,7 +8,18 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class BaseFixer:
|
|
11
|
-
"""
|
|
11
|
+
r"""
|
|
12
|
+
Base class for fixing code formatting issues.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
path : str
|
|
17
|
+
Target file or directory to process.
|
|
18
|
+
exclude_pattern : str, default='\.git|\.tox|\.pytest_cache'
|
|
19
|
+
Regular expression describing paths to skip.
|
|
20
|
+
verbose : str, default='default'
|
|
21
|
+
Verbosity mode; ``'diff'`` prints unified diffs for rewritten files.
|
|
22
|
+
"""
|
|
12
23
|
|
|
13
24
|
def __init__(
|
|
14
25
|
self,
|
|
@@ -16,7 +27,6 @@ class BaseFixer:
|
|
|
16
27
|
exclude_pattern: str = r'\.git|\.tox|\.pytest_cache',
|
|
17
28
|
verbose: str = 'default',
|
|
18
29
|
) -> None:
|
|
19
|
-
"""Initialize the fixer with a path and optional exclude pattern."""
|
|
20
30
|
self.path = path
|
|
21
31
|
self.exclude_pattern = exclude_pattern
|
|
22
32
|
self.verbose = verbose
|