docfmt
Reliable docstring formatter for Python
Motivation
Docstring formatters that rebuild the file from a token stream are prone to a particular class of bug: edits computed against one version of the token list get applied to another, so behavior depends on how much unrelated code precedes the docstring being formatted. The symptom is formatting that changes when you add or remove an unrelated class elsewhere in the file.
docfmt is built so that cannot happen:
- Docstrings are located by AST structure, never by token heuristics or by matching line contents.
- The file is never regenerated. Formatting produces a set of non-overlapping character-range replacements against the original source; everything outside a docstring is preserved byte-for-byte.
- Results are verified before they are written. Every formatted file is
checked for AST equivalence (nothing changed but docstring contents) and for
idempotency (
format(format(x)) == format(x)). A failure leaves the file untouched and reports an internal error rather than writing a bad result.
Behavior
docfmt normalizes docstring layout and never mutates author text. Adding a
trailing period is the one exception, and it is opt-in
(--add-summary-period).
Blank lines around docstrings are preserved by default. Normalization is
opt-in per position under [tool.docfmt.blank-lines].
Structured content is copied verbatim and never rewrapped: fenced code blocks, MyST directives, doctests, reST directives and field lists, tables, and lists.
MyST directives
MyST directives nest by widening the fence, so fence length is significant:
```{note}
Test note
```
A block closes only on a fence of the same character with at least as many markers and no info string, so a narrower inner fence is content:
````{note}
```{warning}
Test warning
```
````
Inline constructs such as `False`{l=python} are treated as unbreakable
atoms, so wrapping never splits an inline code span from its role attribute.
Attribute docstrings
A string statement immediately following an assignment at module or class level is an attribute docstring, including annotation-only attributes:
package: str
"""
Import name of the package.
"""
Usage
docfmt --in-place --recursive src test
docfmt --check src # exit 1 if anything would change
docfmt --diff src
Configure via [tool.docfmt] in pyproject.toml:
[tool.docfmt]
in-place = true
recursive = true
summary-on-own-line = true
| Key | Default | Meaning |
|---|---|---|
line-length |
black's, else 88 | wrap width; 0 disables wrapping |
summary-on-own-line |
false |
put the summary below the opening quotes |
blank-after-description |
false |
blank line before the closing quotes |
force-reflow |
false |
refill prose that already fits |
add-summary-period |
false |
append a period to summaries |
exclude |
[] |
path fragments to skip when recursing |
line-length is left unset by default and picked up from
[tool.black] line-length when black is configured, falling back to 88.
Blank-line rules live in their own table. Each is a count, or "preserve" to
leave the author's spacing alone:
[tool.docfmt.blank-lines]
before-class = "preserve"
after-module = 1
after-class = 1
after-function = "preserve"
after-attribute = 1
Exit codes
| Code | Meaning |
|---|---|
| 0 | Nothing to do, or changes written in in-place mode |
| 1 | Check mode: files would change |
| 2 | Error; no file was modified |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file docfmt-0.1.0.tar.gz.
File metadata
- Download URL: docfmt-0.1.0.tar.gz
- Upload date:
- Size: 16.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6877ada2317698f5f2f3c3738ba823820eeb804e2d873a0a40838688e950bfc0
|
|
| MD5 |
ba202c324d69e85c194de835cf423def
|
|
| BLAKE2b-256 |
4b7fe8c68ccb844b62c0aced64e33544f4c6a98d371091b82df2b766091c9d59
|
File details
Details for the file docfmt-0.1.0-py3-none-any.whl.
File metadata
- Download URL: docfmt-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa0b085328e9208d80c559e7348ec06b581f04f2b528558bfff5b18bc56127f0
|
|
| MD5 |
ce0e898caccc8b55e9cf2aae3e84b1a2
|
|
| BLAKE2b-256 |
80b8473c2a2d3848dc0c0cd74103cd949ca13870471b10ac562eb4b401921383
|