format-docstring 0.1.8__tar.gz → 0.2.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.
- format_docstring-0.2.0/.pre-commit-config.yaml +83 -0
- format_docstring-0.2.0/AGENTS.md +130 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/CHANGELOG.md +23 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/PKG-INFO +156 -11
- {format_docstring-0.1.8 → format_docstring-0.2.0}/README.md +155 -9
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/base_fixer.py +38 -4
- format_docstring-0.2.0/format_docstring/docstring_rewriter.py +577 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/line_wrap_google.py +5 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/line_wrap_numpy.py +318 -27
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/line_wrap_utils.py +76 -40
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/main_jupyter.py +21 -6
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/main_py.py +16 -1
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/PKG-INFO +156 -11
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/SOURCES.txt +9 -1
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/requires.txt +0 -1
- {format_docstring-0.1.8 → format_docstring-0.2.0}/muff.toml +1 -1
- {format_docstring-0.1.8 → format_docstring-0.2.0}/pyproject.toml +1 -2
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/helpers.py +2 -1
- format_docstring-0.2.0/tests/test_base_fixer.py +47 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_config.py +2 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/fix_rst_backticks.txt +1 -1
- format_docstring-0.2.0/tests/test_data/end_to_end/numpy/no_format_docstring_comment.txt +54 -0
- format_docstring-0.2.0/tests/test_data/end_to_end/numpy/parameter_signature_sync.txt +197 -0
- format_docstring-0.2.0/tests/test_data/end_to_end/numpy/returns_signature_sync.txt +169 -0
- format_docstring-0.2.0/tests/test_data/end_to_end/numpy/section_headings_with_colons.txt +68 -0
- format_docstring-0.2.0/tests/test_data/jupyter/before.ipynb +28 -0
- format_docstring-0.2.0/tests/test_data/jupyter/verbose_before.ipynb +28 -0
- format_docstring-0.2.0/tests/test_data/line_wrap/numpy/section_headings_with_colons.txt +60 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_docstring_rewriter.py +5 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_line_wrap_numpy.py +3 -1
- format_docstring-0.2.0/tests/test_main_jupyter.py +90 -0
- format_docstring-0.2.0/tests/test_main_py.py +88 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tox.ini +15 -25
- format_docstring-0.1.8/.pre-commit-config.yaml +0 -42
- format_docstring-0.1.8/CLAUDE.md +0 -151
- format_docstring-0.1.8/format_docstring/docstring_rewriter.py +0 -341
- format_docstring-0.1.8/tests/test_main_jupyter.py +0 -45
- format_docstring-0.1.8/tests/test_main_py.py +0 -42
- {format_docstring-0.1.8 → format_docstring-0.2.0}/.github/workflows/python-package.yml +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/.github/workflows/python-publish.yml +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/.gitignore +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/.pre-commit-hooks.yaml +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/LICENSE +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/__init__.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring/config.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/dependency_links.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/entry_points.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/format_docstring.egg-info/top_level.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/requirements.dev +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/setup.cfg +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/__init__.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/README.md +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/four_level_nested_classes.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/indent_misaligned_all.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/new_lines_before_and_after.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/single_line_docstring.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/end_to_end/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/after.ipynb +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/after.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/after_50.ipynb +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/after_50.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/before.ipynb +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/integration_test/numpy/before.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/README.md +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/colon_spacing_fix.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/contents_that_are_not_wrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/default_value_standardization.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/empty_lines_are_respected.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/examples_section.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/existing_linebreaks_should_not_be_respected.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/fix_rst_backticks.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/indent_four_levels_16_spaces_width_10.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/indent_two_levels_8_spaces.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/line_length_2.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/mismatched_underlines.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/mismatched_underlines_one_dash.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/mismatched_underlines_two_dashes.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/module_level_docstring.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/param_signature_without_type.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/parameters_returns_raises_wrapping.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/returns_signature_and_description.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/section_title_fixed.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/sections_notes_examples.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/signature_line_is_not_wrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/texts_are_rewrapped.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/line_wrap/numpy/very_long_unbreakable_word.txt +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_data/playground.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_line_wrap_google.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_line_wrap_utils.py +0 -0
- {format_docstring-0.1.8 → format_docstring-0.2.0}/tests/test_playground.py +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
repos:
|
|
3
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
4
|
+
rev: v6.0.0
|
|
5
|
+
hooks:
|
|
6
|
+
- id: trailing-whitespace
|
|
7
|
+
- id: end-of-file-fixer
|
|
8
|
+
exclude: \.json$|\.ipynb$
|
|
9
|
+
- id: debug-statements
|
|
10
|
+
- id: double-quote-string-fixer
|
|
11
|
+
- id: requirements-txt-fixer
|
|
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
|
|
21
|
+
- repo: https://github.com/asottile/pyupgrade
|
|
22
|
+
rev: v3.20.0
|
|
23
|
+
hooks:
|
|
24
|
+
- id: pyupgrade
|
|
25
|
+
args: [--py310-plus]
|
|
26
|
+
- repo: https://github.com/jsh9/muff-pre-commit
|
|
27
|
+
rev: 0.13.2
|
|
28
|
+
hooks:
|
|
29
|
+
- id: muff-format
|
|
30
|
+
args: [--config, muff.toml]
|
|
31
|
+
- repo: https://github.com/jsh9/blank-line-after-blocks
|
|
32
|
+
rev: 0.1.4
|
|
33
|
+
hooks:
|
|
34
|
+
- id: blank-line-after-blocks
|
|
35
|
+
- id: blank-line-after-blocks-jupyter
|
|
36
|
+
- repo: https://github.com/lyz-code/yamlfix
|
|
37
|
+
rev: 1.18.0
|
|
38
|
+
hooks:
|
|
39
|
+
- id: yamlfix
|
|
40
|
+
- repo: https://github.com/hukkin/mdformat
|
|
41
|
+
rev: 1.0.0
|
|
42
|
+
hooks:
|
|
43
|
+
- id: mdformat
|
|
44
|
+
args: [--wrap, '79', --number]
|
|
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
|
|
56
|
+
- repo: https://github.com/jsh9/markdown-toc-creator
|
|
57
|
+
rev: 0.0.11
|
|
58
|
+
hooks:
|
|
59
|
+
- id: markdown-toc-creator
|
|
60
|
+
- repo: local
|
|
61
|
+
hooks:
|
|
62
|
+
- id: format-docstring
|
|
63
|
+
name: Format self (python docstrings)
|
|
64
|
+
entry: python
|
|
65
|
+
args: [-m, format_docstring.main_py, --verbose, diff]
|
|
66
|
+
language: python
|
|
67
|
+
types: [python]
|
|
68
|
+
exclude: ^tests/test_data/
|
|
69
|
+
additional_dependencies:
|
|
70
|
+
- click>=8.0
|
|
71
|
+
- jupyter-notebook-parser>=0.1.4
|
|
72
|
+
- tomli>=1.1.0
|
|
73
|
+
- id: format-docstring-jupyter
|
|
74
|
+
name: Format self (docstrings in Jupyter notebooks)
|
|
75
|
+
entry: python
|
|
76
|
+
args: [-m, format_docstring.main_jupyter, --verbose, diff]
|
|
77
|
+
language: python
|
|
78
|
+
files: ^.*\.ipynb$
|
|
79
|
+
exclude: ^tests/test_data/
|
|
80
|
+
additional_dependencies:
|
|
81
|
+
- click>=8.0
|
|
82
|
+
- jupyter-notebook-parser>=0.1.4
|
|
83
|
+
- tomli>=1.1.0
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This guide briefs coding agents working on `format-docstring`. Use it to get
|
|
4
|
+
oriented before making changes.
|
|
5
|
+
|
|
6
|
+
## Quick Snapshot
|
|
7
|
+
|
|
8
|
+
- Formats NumPy-style docstrings (with experimental Google support) in `.py`
|
|
9
|
+
files and Jupyter notebooks while preserving surrounding code.
|
|
10
|
+
- Distributed as a CLI (`format-docstring`, `format-docstring-jupyter`) with
|
|
11
|
+
minimum Python 3.10, packaged via `setuptools`.
|
|
12
|
+
- Core dependencies: `click`, `docstring_parser_fork`,
|
|
13
|
+
`jupyter-notebook-parser`, and `tomli/tomllib` for configuration loading.
|
|
14
|
+
- Version is sourced dynamically in `format_docstring/__init__.py`.
|
|
15
|
+
|
|
16
|
+
## Repository Layout
|
|
17
|
+
|
|
18
|
+
- `format_docstring/main_py.py` – Click CLI for Python files; validates input
|
|
19
|
+
and delegates to `PythonFileFixer`.
|
|
20
|
+
- `format_docstring/main_jupyter.py` – CLI for `.ipynb` files built on
|
|
21
|
+
`JupyterNotebookParser`/`JupyterNotebookRewriter`.
|
|
22
|
+
- `format_docstring/base_fixer.py` – Shared directory traversal, exclusion
|
|
23
|
+
regex handling, and `fix_one_directory_or_one_file` orchestration.
|
|
24
|
+
- `format_docstring/docstring_rewriter.py` – AST-based docstring extraction and
|
|
25
|
+
replacement that leaves non-docstring text untouched.
|
|
26
|
+
- `format_docstring/line_wrap_numpy.py` / `line_wrap_google.py` –
|
|
27
|
+
Style-specific wrapping helpers; NumPy path is the production code path,
|
|
28
|
+
Google is partial.
|
|
29
|
+
- `format_docstring/line_wrap_utils.py` – Shared utilities for wrapping (indent
|
|
30
|
+
management, bullet handling, preserving literal blocks, etc.).
|
|
31
|
+
- `format_docstring/config.py` – `pyproject.toml` discovery, parsing, and Click
|
|
32
|
+
default injection.
|
|
33
|
+
- `tests/` – Pytest suite with fixture-driven cases in `tests/test_data/`; see
|
|
34
|
+
`tests/helpers.py` for fixture loading helpers.
|
|
35
|
+
|
|
36
|
+
## Implementation Notes
|
|
37
|
+
|
|
38
|
+
- `docstring_rewriter.fix_src` parses with `ast.parse`, collects docstring
|
|
39
|
+
literals, and rewrites source slices using absolute offsets from
|
|
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
|
+
- Wrapping honors NumPy section heuristics, rST constructs, code fences,
|
|
48
|
+
`Examples` prompts, and literal blocks introduced by `::`.
|
|
49
|
+
- `_normalize_signature_segment` flattens multiline annotations via
|
|
50
|
+
`ast.unparse` but uses token-level replay to preserve the author's quoting
|
|
51
|
+
style for forward references and string defaults.
|
|
52
|
+
- CLI exposes `--docstring-style`, but the Python entry-point currently raises
|
|
53
|
+
if a non-NumPy style is requested; Jupyter flow passes style through
|
|
54
|
+
unchanged.
|
|
55
|
+
- `BaseFixer` subclasses return `1` when any file changed so callers can
|
|
56
|
+
surface non-zero exit codes.
|
|
57
|
+
- Notebook fixer round-trips JSON via `json.dump(..., indent=1)` and rewrites
|
|
58
|
+
cells only when content changes, preserving magics with `reconstruct_source`.
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
- User-facing configuration lives under `[tool.format_docstring]` inside
|
|
63
|
+
`pyproject.toml` and supports `line_length`, `docstring_style`, `exclude`,
|
|
64
|
+
`fix_rst_backticks`, and `verbose` (`default` or `diff` to print unified
|
|
65
|
+
diffs on rewrites).
|
|
66
|
+
- `config.inject_config_from_file` auto-discovers the nearest `pyproject.toml`
|
|
67
|
+
(walking up from targets) and merges values into Click’s `default_map`.
|
|
68
|
+
- Default exclude pattern is `\.git|\.tox|\.pytest_cache`; tests tweak it as
|
|
69
|
+
needed.
|
|
70
|
+
|
|
71
|
+
## Development Workflow
|
|
72
|
+
|
|
73
|
+
- Install: `pip install -e .` for the project,
|
|
74
|
+
`pip install -r requirements.dev` for tooling.
|
|
75
|
+
- Tests: `pytest --tb=long`, or target modules such as
|
|
76
|
+
`pytest tests/test_docstring_rewriter.py`.
|
|
77
|
+
- Lint/format: `muff check --fix --config=muff.toml format_docstring tests`,
|
|
78
|
+
`muff format --diff --config=muff.toml format_docstring tests`.
|
|
79
|
+
- Type checking: `mypy format_docstring/`.
|
|
80
|
+
- Tox: `tox` for the full matrix (py310–py313, mypy, lint), or focused runs
|
|
81
|
+
like `tox -e py311`, `tox -e mypy`, `tox -e muff-format`.
|
|
82
|
+
- CLI smoke tests: `format-docstring --help`,
|
|
83
|
+
`format-docstring-jupyter --help`.
|
|
84
|
+
- Pre-commit: `pre-commit run -a`.
|
|
85
|
+
|
|
86
|
+
## Testing Notes
|
|
87
|
+
|
|
88
|
+
- Fixture files under `tests/test_data/line_wrap` and
|
|
89
|
+
`tests/test_data/end_to_end` use `LINE_LENGTH: <int>` headers followed by
|
|
90
|
+
`BEFORE`/`AFTER` sections split by `**********`.
|
|
91
|
+
- `tests/test_playground.py` focuses on regression snippets;
|
|
92
|
+
`tests/test_config.py` exercises config discovery and CLI overrides.
|
|
93
|
+
- When modifying wrapping rules, update both the helper (`line_wrap_utils.py`)
|
|
94
|
+
and the corresponding expectation files in `tests/test_data/`.
|
|
95
|
+
|
|
96
|
+
## Style Guidance
|
|
97
|
+
|
|
98
|
+
- Formatting rules mirror `muff.toml` (line length 79, single quotes, NumPy
|
|
99
|
+
docstring convention). Respect these when adding code.
|
|
100
|
+
- Keep docstring style tests conservative: avoid mutating non-docstring
|
|
101
|
+
content, and add regression cases whenever handling around literal sections
|
|
102
|
+
or tables changes.
|
|
103
|
+
|
|
104
|
+
## What is a "signature line"?
|
|
105
|
+
|
|
106
|
+
They are the lines in the docstring where input and return args are defined,
|
|
107
|
+
for example, in this docstring:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
"""
|
|
111
|
+
Do something
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
arg1 : str
|
|
116
|
+
Arg 1
|
|
117
|
+
arg2 : int = 2
|
|
118
|
+
Arg 2
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
dict[str, str]
|
|
123
|
+
The mapping
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Signature lines are:
|
|
127
|
+
|
|
128
|
+
- arg1 : str
|
|
129
|
+
- arg2 : int = 2
|
|
130
|
+
- dict[str, str]
|
|
@@ -6,6 +6,29 @@ 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.0] - 2025-10-20
|
|
10
|
+
|
|
11
|
+
- Added
|
|
12
|
+
- AST-driven synchronization of NumPy `Parameters` and `Returns` signature
|
|
13
|
+
lines with the function signature, including tuple element expansion for
|
|
14
|
+
multi-line return blocks
|
|
15
|
+
- Full diff
|
|
16
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.9...0.2.0
|
|
17
|
+
|
|
18
|
+
## [0.1.9] - 2025-10-16
|
|
19
|
+
|
|
20
|
+
- Added
|
|
21
|
+
- A "`# no-format-docstring`" directive to ignore certain docstring
|
|
22
|
+
- Verbose diff output via `--verbose diff` and
|
|
23
|
+
`[tool.format_docstring] verbose`
|
|
24
|
+
- Normalize NumPy section headings that include trailing colons (e.g.,
|
|
25
|
+
`Parameters:`); also, fix Google-style "Arg" header into "Parameters"
|
|
26
|
+
- Changed
|
|
27
|
+
- Added "self format" pre-commit hook to format docstrings within this repo
|
|
28
|
+
with its own formatting logic
|
|
29
|
+
- Full diff
|
|
30
|
+
- https://github.com/jsh9/format-docstring/compare/0.1.8...0.1.9
|
|
31
|
+
|
|
9
32
|
## [0.1.8] - 2025-10-14
|
|
10
33
|
|
|
11
34
|
- Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: format-docstring
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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>
|
|
@@ -27,7 +27,6 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: jupyter-notebook-parser>=0.1.4
|
|
29
29
|
Requires-Dist: click>=8.0
|
|
30
|
-
Requires-Dist: docstring_parser_fork>=0.0.14
|
|
31
30
|
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
32
31
|
Dynamic: license-file
|
|
33
32
|
|
|
@@ -35,6 +34,8 @@ Dynamic: license-file
|
|
|
35
34
|
|
|
36
35
|
A Python formatter to automatically format numpy-style docstrings.
|
|
37
36
|
|
|
37
|
+
______________________________________________________________________
|
|
38
|
+
|
|
38
39
|
**Table of Contents:**
|
|
39
40
|
|
|
40
41
|
<!--TOC-->
|
|
@@ -46,32 +47,38 @@ A Python formatter to automatically format numpy-style docstrings.
|
|
|
46
47
|
- [2.3. Minor typos can be automatically fixed](#23-minor-typos-can-be-automatically-fixed)
|
|
47
48
|
- [2.4. Default value declarations are standardized](#24-default-value-declarations-are-standardized)
|
|
48
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)
|
|
49
51
|
- [3. Installation](#3-installation)
|
|
50
52
|
- [4. Usage](#4-usage)
|
|
51
53
|
- [4.1. Command Line Interface](#41-command-line-interface)
|
|
52
54
|
- [4.2. Pre-commit Hook](#42-pre-commit-hook)
|
|
55
|
+
- [4.3. Opting Out of Formatting](#43-opting-out-of-formatting)
|
|
53
56
|
- [5. Configuration](#5-configuration)
|
|
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
|
|
@@ -281,6 +392,19 @@ Then install the pre-commit hook:
|
|
|
281
392
|
pre-commit install
|
|
282
393
|
```
|
|
283
394
|
|
|
395
|
+
### 4.3. Opting Out of Formatting
|
|
396
|
+
|
|
397
|
+
Add a comment containing `no-format-docstring` on the same line as the closing
|
|
398
|
+
triple quotes to prevent the formatter from touching that docstring:
|
|
399
|
+
`""" ... """ # no-format-docstring`.
|
|
400
|
+
|
|
401
|
+
You can combine this "no-format-docstring" with other directives like "noqa".
|
|
402
|
+
|
|
403
|
+
Tip: If you only want to keep specific formatter changes inside a docstring,
|
|
404
|
+
first run `format-docstring`, accept the parts you like, revert the edits you
|
|
405
|
+
dislike, and then add an inline `# no-format-docstring` comment so future runs
|
|
406
|
+
leave that docstring untouched.
|
|
407
|
+
|
|
284
408
|
## 5. Configuration
|
|
285
409
|
|
|
286
410
|
### 5.1. Command-Line Options
|
|
@@ -291,6 +415,8 @@ pre-commit install
|
|
|
291
415
|
default: `numpy`). Note: Currently only `numpy` style is fully supported.
|
|
292
416
|
- `--fix-rst-backticks BOOL`: Automatically fix single backticks to double
|
|
293
417
|
backticks per rST syntax (default: True)
|
|
418
|
+
- `--verbose CHOICE`: Logging detail level (`default` keeps the existing
|
|
419
|
+
behaviour, `diff` prints unified diffs when rewrites happen)
|
|
294
420
|
- `--exclude TEXT`: Regex pattern to exclude files/directories (default:
|
|
295
421
|
`\.git|\.tox|\.pytest_cache`)
|
|
296
422
|
- `--config PATH`: Path to a `pyproject.toml` config file. If not specified,
|
|
@@ -311,6 +437,9 @@ format-docstring --line-length 72 src/
|
|
|
311
437
|
# Format Jupyter notebooks excluding certain directories
|
|
312
438
|
format-docstring-jupyter --exclude "\.git|\.venv|__pycache__" notebooks/
|
|
313
439
|
|
|
440
|
+
# Preview changes with unified diffs
|
|
441
|
+
format-docstring --verbose diff src/
|
|
442
|
+
|
|
314
443
|
# Use a specific config file
|
|
315
444
|
format-docstring --config path/to/pyproject.toml src/
|
|
316
445
|
|
|
@@ -332,6 +461,7 @@ line_length = 79
|
|
|
332
461
|
docstring_style = "numpy"
|
|
333
462
|
fix_rst_backticks = true
|
|
334
463
|
exclude = "\\.git|\\.venv|__pycache__"
|
|
464
|
+
verbose = "default" # or "diff" to print unified diffs
|
|
335
465
|
```
|
|
336
466
|
|
|
337
467
|
**Available options:**
|
|
@@ -344,6 +474,21 @@ exclude = "\\.git|\\.venv|__pycache__"
|
|
|
344
474
|
backticks per rST syntax (default: `true`)
|
|
345
475
|
- `exclude` (str): Regex pattern to exclude files/directories (default:
|
|
346
476
|
`"\\.git|\\.tox|\\.pytest_cache"`)
|
|
477
|
+
- `verbose` (str): Logging detail level (`"default"` or `"diff"`)
|
|
347
478
|
|
|
348
479
|
The tool searches for `pyproject.toml` starting from the target file/directory
|
|
349
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
|