Metadata-Version: 2.4
Name: docstring_generator_ext
Version: 2.0.5
Summary: Generate Docstrings with type-hint information.
Author-email: FelixTheC <fberndt87@gmail.com>
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Classifier: Topic :: Software Development :: Documentation
Classifier: Typing :: Typed
Requires-Python: >=3.13
Description-Content-Type: text/markdown
Requires-Dist: pybind11>=3.0.4

# Docstring Generator Extension

[![C++ Tests](https://github.com/FelixTheC/docstring_generator_ext/actions/workflows/cpp-tests.yml/badge.svg)](https://github.com/FelixTheC/docstring_generator_ext/actions/workflows/cpp-tests.yml)
[![Build Extension](https://github.com/FelixTheC/docstring_generator_ext/actions/workflows/check-build-ext.yml/badge.svg)](https://github.com/FelixTheC/docstring_generator_ext/actions/workflows/check-build-ext.yml)
[![PyPI version](https://img.shields.io/pypi/v/docstring_generator_ext.svg)](https://pypi.org/project/docstring_generator_ext/)
[![Python versions](https://img.shields.io/pypi/pyversions/docstring_generator_ext.svg)](https://pypi.org/project/docstring_generator_ext/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

`docstring_generator_ext` is a high-performance Python extension written in C++ (using pybind11) designed to automatically generate and inject docstrings into Python source files. It leverages Python's `ast` module to extract type-hint information and function signatures to create well-formatted docstrings in various styles.

## Features

- **Automatic Docstring Injection**: Parses Python files and inserts docstrings for functions and methods.
- **Async-function support**: Handles both `def` and `async def` functions transparently.
- **Type-Hint Awareness**: Extracts type information from annotations and default values.
- **Multiple Styles**: Supports popular docstring formats:
  - **reST** (reStructuredText)
  - **Google** style
  - **NumPy** style
- **Format-style detection**: Automatically detects the style of an existing docstring and refuses to silently mix styles unless `allow_overwrite=True` is passed.
- **Style conversion**: With `allow_overwrite=True`, converts a docstring written in one style to another in a single call.
- **Exception detection**: Analyses the function body with Python's `ast` module to identify raised exceptions and include them in the docstring.
- **Docstring coverage auditing**: `check_docstring()` reports how many functions in a file have complete, partial, or missing docstrings without modifying the file.
- **High Performance**: Core logic implemented in C++ for fast processing.
- **Preserves Existing Content**: Keeps manually written descriptions across re-runs using special in-docstring markers:
  - `$N` binds the text on that line to the *N*-th function parameter.
  - `>>` provides the return-value description.

## Installation

### Prerequisites

- Python 3.13 or higher
- A C++ compiler with C++20 support (e.g., GCC, Clang, or MSVC)
- `pybind11`

### Building from Source

1. Clone the repository:
   ```bash
   git clone https://github.com/FelixTheC/docstring_generator_ext.git
   cd docstring_generator_ext
   ```

2. Install the `build` package:
   ```bash
   pip install build
   ```

3. Build the package:
   ```bash
   python -m build
   ```

4. Install the built wheel:
   ```bash
   pip install dist/docstring_generator_ext-*.whl
   ```

## Usage

After installation, you can use the extension in your Python scripts:

```python
import docstring_generator_ext

# Path to the Python file you want to process
file_path = "path/to/your_script.py"

# Choose a style: GOOGLE, NUMPY, or reST
style = docstring_generator_ext.DocstringFormatStyle.GOOGLE

# Generate and inject docstrings
docstring_generator_ext.parse_file(file_path, style)
```

### Overwriting an existing docstring format

By default, `parse_file` refuses to overwrite a docstring that was already written in a **different** style than the one you requested, and will print a warning instead. Pass `allow_overwrite=True` to let the extension convert the existing docstring to the new style:

```python
import docstring_generator_ext

file_path = "path/to/your_script.py"
style = docstring_generator_ext.DocstringFormatStyle.NUMPY

# Convert any existing docstring style to NUMPY — previous style will be removed
docstring_generator_ext.parse_file(file_path, style, allow_overwrite=True)
```

### Auditing docstring coverage

You can audit an existing file to see how well its functions are documented, without making any changes:

```python
import docstring_generator_ext

# Path to the Python file you want to audit
file_path = "path/to/your_script.py"

# Returns a dict with docstring coverage statistics
result = docstring_generator_ext.check_docstring(file_path)

print(f"Functions checked  : {result['num_functions_checked']}")
print(f"Complete docstrings: {result['complete_docstrings']}")
print(f"Partial docstrings : {result['partial_docstrings']}")
print(f"No docstrings      : {result['no_docstrings']}")
```

The returned dictionary always contains four keys:

| Key | Description |
|-----|-------------|
| `num_functions_checked` | Total number of functions/methods found in the file |
| `complete_docstrings` | Functions whose docstring fully matches the signature |
| `partial_docstrings` | Functions with an incomplete or outdated docstring |
| `no_docstrings` | Functions with no docstring at all |

### Docstring Styles

The extension provides an enum `DocstringFormatStyle` to choose the desired output:

- `docstring_generator_ext.DocstringFormatStyle.reST`
- `docstring_generator_ext.DocstringFormatStyle.GOOGLE`
- `docstring_generator_ext.DocstringFormatStyle.NUMPY`

### Preserving descriptions with special markers

When the extension processes a file that already contains docstrings, it tries to keep manually written descriptions in place. Two marker conventions are supported:

#### `$N` — argument description markers

Place a `$` followed by the **1-based index** of the parameter inside the docstring to bind a free-form description to that argument. The marker and the text on its line are extracted and attached to the corresponding parameter; the `$N` line is then removed from the generated docstring.

```python
def add(a: int, b: int) -> int:
    """Add two numbers together.

    $1 The first operand.
    $2 The second operand.
    """
    return a + b
```

After the next `parse_file` run the descriptions will be wired to `a` and `b` automatically.

```python
def add(a: int, b: int) -> int:
    """Add two numbers together.

    Args:
        a (int): The first operand.
        b (int): The second operand.
    Returns:
        int
    """
    return a + b
```

#### `>>` — return description marker

Place `>>` on its own line inside the docstring to provide the description for the return value. The text after `>>` on that line is extracted as the return description, and the marker line is removed.

```python
def square(x: int) -> int:
    """Square a number.

    >> The squared value of x.
    """
    return x * x
```
After the next `parse_file` run the descriptions will be wired to `Returns` description automatically.
```python
def square(x: int) -> int:
    """Square a number.

    Args:
        x (int):
    Returns:
        int: The squared value of x.
    """
    return x * x
```

## C++20

The core of this extension is written in **C++20** to take full advantage of the modern standard's best algorithms and features:

- **`std::format`**: Used for clean, type-safe string formatting throughout the docstring generation logic.
- **Ranges & views**: C++20 ranges enable expressive, composable data transformations without raw loops.
- **Concepts**: Improve template code clarity and provide better compiler error messages.
- **`std::span`**: Provides safe, bounds-checked views over contiguous data without ownership overhead.

### Compiler Requirements

Building from source requires a C++ compiler with full C++20 support:

| Platform | Minimum version         |
|----------|-------------------------|
| Linux    | GCC 11+ / Clang 14+     |
| macOS    | Apple Clang 15+ / GCC 13+ (via Homebrew) |
| Windows  | MSVC 2022 (19.30+)      |

Pre-built wheels on [PyPI](https://pypi.org/project/docstring_generator_ext/) are compiled with C++20 enabled and require no special toolchain on the user's side.


## Authors

- **FelixTheC**

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.


