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.
Files changed (107) hide show
  1. {format_docstring-0.1.9 → format_docstring-0.2.1}/.pre-commit-config.yaml +26 -4
  2. {format_docstring-0.1.9 → format_docstring-0.2.1}/AGENTS.md +49 -7
  3. {format_docstring-0.1.9 → format_docstring-0.2.1}/CHANGELOG.md +18 -0
  4. {format_docstring-0.1.9 → format_docstring-0.2.1}/PKG-INFO +135 -10
  5. {format_docstring-0.1.9 → format_docstring-0.2.1}/README.md +134 -9
  6. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/base_fixer.py +12 -2
  7. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/docstring_rewriter.py +204 -10
  8. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_google.py +5 -0
  9. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_numpy.py +288 -5
  10. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/line_wrap_utils.py +14 -8
  11. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/PKG-INFO +135 -10
  12. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/SOURCES.txt +4 -0
  13. {format_docstring-0.1.9 → format_docstring-0.2.1}/pyproject.toml +1 -1
  14. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/fix_rst_backticks.txt +1 -1
  15. format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_dont_sync_raises.txt +48 -0
  16. format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_parameters.txt +197 -0
  17. format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_returns.txt +226 -0
  18. format_docstring-0.2.1/tests/test_data/end_to_end/numpy/signature_sync_yields.txt +103 -0
  19. {format_docstring-0.1.9 → format_docstring-0.2.1}/tox.ini +15 -25
  20. {format_docstring-0.1.9 → format_docstring-0.2.1}/.github/workflows/python-package.yml +0 -0
  21. {format_docstring-0.1.9 → format_docstring-0.2.1}/.github/workflows/python-publish.yml +0 -0
  22. {format_docstring-0.1.9 → format_docstring-0.2.1}/.gitignore +0 -0
  23. {format_docstring-0.1.9 → format_docstring-0.2.1}/.pre-commit-hooks.yaml +0 -0
  24. {format_docstring-0.1.9 → format_docstring-0.2.1}/LICENSE +0 -0
  25. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/__init__.py +0 -0
  26. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/config.py +0 -0
  27. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/main_jupyter.py +0 -0
  28. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring/main_py.py +0 -0
  29. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/dependency_links.txt +0 -0
  30. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/entry_points.txt +0 -0
  31. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/requires.txt +0 -0
  32. {format_docstring-0.1.9 → format_docstring-0.2.1}/format_docstring.egg-info/top_level.txt +0 -0
  33. {format_docstring-0.1.9 → format_docstring-0.2.1}/muff.toml +0 -0
  34. {format_docstring-0.1.9 → format_docstring-0.2.1}/requirements.dev +0 -0
  35. {format_docstring-0.1.9 → format_docstring-0.2.1}/setup.cfg +0 -0
  36. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/__init__.py +0 -0
  37. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/helpers.py +0 -0
  38. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_base_fixer.py +0 -0
  39. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_config.py +0 -0
  40. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/README.md +0 -0
  41. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/colon_spacing_fix.txt +0 -0
  42. {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
  43. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/default_value_standardization.txt +0 -0
  44. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/empty_lines_are_respected.txt +0 -0
  45. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/examples_section.txt +0 -0
  46. {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
  47. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/four_level_nested_classes.txt +0 -0
  48. {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
  49. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/indent_misaligned_all.txt +0 -0
  50. {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
  51. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/line_length_2.txt +0 -0
  52. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines.txt +0 -0
  53. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines_one_dash.txt +0 -0
  54. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/mismatched_underlines_two_dashes.txt +0 -0
  55. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/module_level_docstring.txt +0 -0
  56. {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
  57. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/no_format_docstring_comment.txt +0 -0
  58. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/param_signature_without_type.txt +0 -0
  59. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/parameters_returns_raises_wrapping.txt +0 -0
  60. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/returns_signature_and_description.txt +0 -0
  61. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/section_headings_with_colons.txt +0 -0
  62. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/section_title_fixed.txt +0 -0
  63. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/sections_notes_examples.txt +0 -0
  64. {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
  65. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/single_line_docstring.txt +0 -0
  66. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/texts_are_rewrapped.txt +0 -0
  67. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/end_to_end/numpy/very_long_unbreakable_word.txt +0 -0
  68. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after.ipynb +0 -0
  69. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after.py +0 -0
  70. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after_50.ipynb +0 -0
  71. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/after_50.py +0 -0
  72. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/before.ipynb +0 -0
  73. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/integration_test/numpy/before.py +0 -0
  74. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/jupyter/before.ipynb +0 -0
  75. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/jupyter/verbose_before.ipynb +0 -0
  76. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/README.md +0 -0
  77. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/colon_spacing_fix.txt +0 -0
  78. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/contents_that_are_not_wrapped.txt +0 -0
  79. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/default_value_standardization.txt +0 -0
  80. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/empty_lines_are_respected.txt +0 -0
  81. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/examples_section.txt +0 -0
  82. {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
  83. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/fix_rst_backticks.txt +0 -0
  84. {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
  85. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/indent_two_levels_8_spaces.txt +0 -0
  86. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/line_length_2.txt +0 -0
  87. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines.txt +0 -0
  88. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines_one_dash.txt +0 -0
  89. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/mismatched_underlines_two_dashes.txt +0 -0
  90. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/module_level_docstring.txt +0 -0
  91. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/param_signature_without_type.txt +0 -0
  92. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/parameters_returns_raises_wrapping.txt +0 -0
  93. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/returns_signature_and_description.txt +0 -0
  94. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/section_headings_with_colons.txt +0 -0
  95. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/section_title_fixed.txt +0 -0
  96. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/sections_notes_examples.txt +0 -0
  97. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/signature_line_is_not_wrapped.txt +0 -0
  98. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/texts_are_rewrapped.txt +0 -0
  99. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/line_wrap/numpy/very_long_unbreakable_word.txt +0 -0
  100. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_data/playground.py +0 -0
  101. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_docstring_rewriter.py +0 -0
  102. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_google.py +0 -0
  103. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_numpy.py +0 -0
  104. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_line_wrap_utils.py +0 -0
  105. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_main_jupyter.py +0 -0
  106. {format_docstring-0.1.9 → format_docstring-0.2.1}/tests/test_main_py.py +0 -0
  107. {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.7.22
41
+ rev: 1.0.0
35
42
  hooks:
36
43
  - id: mdformat
37
44
  args: [--wrap, '79', --number]
38
- additional_dependencies: [mdformat-tables]
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.9
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
- Compared with [`docformatter`](https://github.com/PyCQA/docformatter) and
66
- [`pydocstringformatter`](https://github.com/DanielNoord/pydocstringformatter),
67
- this tool (`format-docstring`) goes further by intelligently wrapping docstring
68
- contents, fixing common typos, etc.
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
- The formatting that would be done by
71
- [docformatter](https://github.com/PyCQA/docformatter) and
72
- [pydocstringformatter](https://github.com/DanielNoord/pydocstringformatter) can
73
- be readily handled by [Ruff](https://github.com/astral-sh/ruff) or
74
- [Black](https://github.com/psf/black).
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
- Compared with [`docformatter`](https://github.com/PyCQA/docformatter) and
34
- [`pydocstringformatter`](https://github.com/DanielNoord/pydocstringformatter),
35
- this tool (`format-docstring`) goes further by intelligently wrapping docstring
36
- contents, fixing common typos, etc.
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
- The formatting that would be done by
39
- [docformatter](https://github.com/PyCQA/docformatter) and
40
- [pydocstringformatter](https://github.com/DanielNoord/pydocstringformatter) can
41
- be readily handled by [Ruff](https://github.com/astral-sh/ruff) or
42
- [Black](https://github.com/psf/black).
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
- """Base class for fixing code formatting issues."""
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