Project Status
May 17, 2026 · View on GitHub
pymend
Create, update or convert docstrings in existing Python files, managing several styles.
Project Status
Test Status
|Build| |Documentation Status| |Downloads|
|License: MIT| |Code style: black| |linting: pylint| |Ruff| |Checked with pyright| |pre-commit|
Supported Versions
|Supports Python39| |Supports Python310| |Supports Python311| |Supports Python312| |Supports Python313| |Supports Python314|
.. Code Coverage
.. .. image:: https://coveralls.io/repos/github/wagnerpeer/pymend/badge.svg?branch=enhancement%2Fcoveralls .. :target: https://coveralls.io/github/wagnerpeer/pymend?branch=enhancement%2Fcoveralls .. :alt: Test coverage (Coveralls)
Description
Command-line program to generate, update or transform docstrings in python source code.
The app will parse the requested source files for docstrings as well as function signatures and class bodies.
This information is combined to build up complete docstrings for every function and class including place holders for types and descriptions where none could be found elsewhere.
The output format of the docstrings can be chosen between google, numpy, reST and epydoc. This means that the tool can also be used to transform docstrings in the file from one format into another.
Note however that not all section types are supported for all docstring styles.
Partially because they have not been added yet, but also because not every style officially supports the sections from all others.
To get further information please refer to the
documentation <https://pymend.readthedocs.io/en/latest/?badge=latest>__.
The tool offers the choice between generating patch files or directly overwriting the python source files.
Start quickly
- install from PyPi
.. code:: sh
$ pip install pymend
- install from sources:
.. code:: sh
git clone https://github.com/JanEricNitschke/pymend.git
pip install .
or with uv (https://docs.astral.sh/uv/).
cd pymend
uv tool install .
in the case of uv you can prefix all commands below with uv run.
- run from the command line:
.. code:: sh
pymend myfile.py # will generate a patch pymend --write myfile.py # will overwrite the file
- get help:
.. code:: sh
$ pymend -h
Example
To see how pymend looks in action lets consider this example file example.py:
.. code-block:: python
"""summary.""" def my_func(param0, param01: int, param1: str = "Some value", param2: List[str] = {}): """summary.
Args:
param0 (_type_): _description_
param01 (int): _description_
param1 (str, optional): _description_. Defaults to "Some value".
param2 (List[str], optional): _description_. Defaults to {}.
"""
pass
def my_single_return_func1() -> str:
"""_summary_.
Returns
-------
int
Wrong
"""
pass
def my_multi_return_func() -> Tuple[int, str, bool]:
"""_summary_.
Returns
-------
x :
Some integer
y : str
Some string
z : bool
Some bool
"""
pass
class A: def method(self, param1, param2=None) -> int: pass
Now let's use Pymend:
.. code-block:: sh
$ pymend example.py
This produces the following patch file example.py.patch:
.. code-block:: patch
# Patch generated by Pymend v3.2.2
--- a/example.py
+++ b/example.py
@@ -2,11 +2,16 @@
def my_func(param0, param01: int, param1: str = "Some value", param2: List[str] = {}):
"""_summary_.
- Args:
- param0 (_type_): _description_
- param01 (int): _description_
- param1 (str, optional): _description_. Defaults to "Some value".
- param2 (List[str], optional): _description_. Defaults to {}.
+ Parameters
+ ----------
+ param0 : _type_
+ _description_
+ param01 : int
+ _description_
+ param1 : str
+ _description_. Defaults to "Some value".
+ param2 : List[str]
+ _description_. Defaults to {}.
"""
pass
@@ -16,7 +21,7 @@
Returns
-------
- int
+ str
Wrong
"""
pass
@@ -27,7 +32,7 @@
Returns
-------
- x :
+ x : _type_
Some integer
y : str
Some string
@@ -37,5 +42,21 @@
pass
class A:
+ """_summary_.
+
+ Methods
+ -------
+ method(param1, param2=None)
+ _description_
+ """
def method(self, param1, param2=None) -> int:
+ """_summary_.
+
+ Parameters
+ ----------
+ param1 : _type_
+ _description_
+ param2 : _type_
+ _description_ (Default value = None)
+ """
pass
Calling pymend directly with
.. code-block:: sh
$ pymend --write example.py
prints out this information about changed files
.. code-block:: sh
$ Modified docstrings of elements (my_func, my_single_return_func1, my_multi_return_func, A, method) in file example.py.
and results in the final file (the same we would have gotten when applying the patch):
.. code-block:: python
"""_summary_."""
def my_func(param0, param01: int, param1: str = "Some value", param2: List[str] = {}):
"""_summary_.
Parameters
----------
param0 : _type_
_description_
param01 : int
_description_
param1 : str
_description_. Defaults to "Some value".
param2 : List[str]
_description_. Defaults to {}.
"""
pass
def my_single_return_func1() -> str:
"""_summary_.
Returns
-------
str
Wrong
"""
pass
def my_multi_return_func() -> Tuple[int, str, bool]:
"""_summary_.
Returns
-------
x : _type_
Some integer
y : str
Some string
z : bool
Some bool
"""
pass
class A:
"""_summary_.
Methods
-------
method(param1, param2=None)
_description_
"""
def method(self, param1, param2=None) -> int:
"""_summary_.
Parameters
----------
param1 : _type_
_description_
param2 : _type_
_description_ (Default value = None)
"""
pass
Exit codes
PyMend uses exit codes to indicate the result:
- 0: All files well formatted, no issues
- 1: One or more files had issues (would be reformatted or have problems)
- 2: Usage error (e.g. invalid or conflicting command-line options)
- 123: Internal error occurred
.. code:: console
$ pymend src/
All done! ✨ 🍰 ✨
5 files would be left unchanged.
$ echo $?
0
$ pymend src/
would reformat src/main.py
Oh no! 💥 💔 💥
1 file would be reformatted.
$ echo $?
1
$ pymend src/
error: cannot format src/main.py: INTERNAL ERROR
Oh no! 💥 💔 💥
1 file would fail to reformat.
$ echo $?
123
Pre-commit
To use pymend in a pre-commit <https://pre-commit.com/>__ hook just
add the following to your .pre-commit-config.yaml
.. code:: yaml
repos:
- repo: https://github.com/JanEricNitschke/pymend
rev: "v3.2.2"
hooks:
- id: pymend language: python args: ["--write"]
Acknowledgements
This project was inspired by and is originally based upon
pyment <https://github.com/dadadel/pyment/>__. The intended
functionality as well as the main entry point remain largely unchanged.
However additional functionality has been added in the form of ast
traversal for extracting function and class information.
The docstring parsing has been replaced completely with code taken from
the awesome
docstring_parser <https://github.com/rr-/docstring_parser>__ project,
specifically this fork <https://github.com/jsh9/docstring_parser_fork>__.
So far only minor modifications have been made to the docstring parsing functionality. Mainly the addition of the “Methods” section for numpydoc style docstrings. Additionally the code has been linted as well as type hinted.
The code for configuration and file handling as well as the structure of the documentation
is more or less taken directly from black <https://github.com/psf/black/>__.
.. |Build| image:: https://github.com/JanEricNitschke/pymend/actions/workflows/build.yaml/badge.svg :target: https://github.com/JanEricNitschke/pymend/workflows/build.yaml .. |Documentation Status| image:: https://readthedocs.org/projects/pymend/badge/?version=latest :target: https://pymend.readthedocs.io/en/latest/?badge=latest .. |Downloads| image:: https://static.pepy.tech/personalized-badge/pymend?period=total&units=international_system&left_color=grey&right_color=blue&left_text=Downloads :target: https://www.pepy.tech/projects/pymend .. |License: MIT| image:: https://img.shields.io/badge/License-MIT-blue.svg :target: https://github.com/JanEricNitschke/pymend/blob/main/LICENSE .. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/psf/black .. |linting: pylint| image:: https://img.shields.io/badge/linting-pylint-yellowgreen :target: https://github.com/pylint-dev/pylint .. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json :target: https://github.com/charliermarsh/ruff .. |Checked with pyright| image:: https://microsoft.github.io/pyright/img/pyright_badge.svg :target: https://microsoft.github.io/pyright/ .. |pre-commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit :target: https://github.com/pre-commit/pre-commit .. |Supports Python39| image:: https://img.shields.io/badge/python-3.9-blue.svg :target: https://www.python.org/downloads/release/python-390/ .. |Supports Python310| image:: https://img.shields.io/badge/python-3.10-blue.svg :target: https://www.python.org/downloads/release/python-3100/ .. |Supports Python311| image:: https://img.shields.io/badge/python-3.11-blue.svg :target: https://www.python.org/downloads/release/python-3110/ .. |Supports Python312| image:: https://img.shields.io/badge/python-3.12-blue.svg :target: https://www.python.org/downloads/release/python-3120/ .. |Supports Python313| image:: https://img.shields.io/badge/python-3.13-blue.svg :target: https://www.python.org/downloads/release/python-3130/ .. |Supports Python314| image:: https://img.shields.io/badge/python-3.14-blue.svg :target: https://www.python.org/downloads/release/python-3140/