Skip to main content

Re-use segments of your docstrings

Project description

DocStrands

Read the full documentation here

When documenting your functions, you might find yourself documenting the same parameters over and over again. DocStrands provides a framework for re-using docstring information.

Example

Imagine you’re writing an HTTP library. You start with a get function, but add the @docstring decorator to tell DocStrands that it function uses Google-style docstrings.

from docstrands import docstring

@docstring("google")
def get(url: str, headers: dict[str, str], params: dict[str, str]) -> str:
    """
    Makes an HTTP GET request

    Params:
        url: Path to the resource to request
        headers: Dictionary of HTTP headers. Keys will be automatically capitalised.
        params: Dictionary of query parameters which will be URL encoded.

    Returns:
        The raw HTTP response body as a string.
    """

Next, you want to write a corresponding post function. The annoying thing is that many of these parameters are exactly the same as on our get function. Here DocStrands solves this by copying the repeated documentation using @get.copy_* functions:

@get.copy_params("url", "headers")
@get.copy_returns()
@docstring("google")
def post(url: str, headers: dict[str, str], body: bytes) -> str:
    """
    Makes an HTTP POST request.

    Params:
        body: POST body. Text such as JSON will have to be encoded beforehand.
    """

Finally, you can call help to prove this worked correctly:

help(post)
Help on ParsedFunc in module docstrands.parsed_func:

<function post>
    Makes an HTTP POST request.

    Args:
        body: POST body. Text such as JSON will have to be encoded beforehand.
        url: Path to the resource to request
        headers: Dictionary of HTTP headers. Keys will be automatically capitalised.

    Returns:
        : The raw HTTP response body as a string.

Type Annotations

DocStrands supports another approach to re-using documentation: attaching it to types. The above example represents a common case where both functions shared the same return documentation and return type, so we can encode this using Python’s type system:

from typing import Annotated
from docstrands import Description

HttpResponse = Annotated[str, Description("The raw HTTP response body as a string.")]
Url = Annotated[str, Description("Path to the resource to request")]
Headers = Annotated[dict[str, str], Description("Dictionary of HTTP headers. Keys will be automatically capitalised.")]
Params = Annotated[dict[str, str], Description("Dictionary of query parameters which will be URL encoded.")]

Then apply them to our new function. Note that we still need to define the function description, and we still need to use the @docstring decorator:

@docstring("google")
def get(url: Url, headers: Headers, params: Params) -> HttpResponse:
    """
    Makes an HTTP POST request.
    """

help(get)
Help on ParsedFunc in module docstrands.parsed_func:

<function get>
    Makes an HTTP POST request.

    Args:
        url: Path to the resource to request
        headers: Dictionary of HTTP headers. Keys will be automatically capitalised.
        params: Dictionary of query parameters which will be URL encoded.

    Returns:
        : The raw HTTP response body as a string.

Of course, we can then re-use these parameters with post:

Body = Annotated[bytes, Description("POST body. Text such as JSON will have to be encoded beforehand.")]

@docstring("google")
def post(url: Url, headers: Headers, body: Body) -> HttpResponse:
    """
    Makes an HTTP POST request.
    """

help(post)
Help on ParsedFunc in module docstrands.parsed_func:

<function post>
    Makes an HTTP POST request.

    Args:
        url: Path to the resource to request
        headers: Dictionary of HTTP headers. Keys will be automatically capitalised.
        body: POST body. Text such as JSON will have to be encoded beforehand.

    Returns:
        : The raw HTTP response body as a string.

You can even re-use the same types as parameters and return values:

@docstring("google")
def make_accept_headers() -> Headers:
    """
    Calculates the the `Accept`, `Accept-Encoding` and `Accept-Language` headers based on the capacity of the HTTP client
    """

help(make_accept_headers)
Help on ParsedFunc in module docstrands.parsed_func:

<function make_accept_headers>
    Calculates the the `Accept`, `Accept-Encoding` and `Accept-Language` headers based on the capacity of the HTTP client

    Returns:
        : Dictionary of HTTP headers. Keys will be automatically capitalised.

Alternatives

There are other solutions to this problem.

We could choose to not use DocStrands at all, but then post would have an incomplete docstring:

We could also copy the entire docstring from get and add it to post along with the extra body parameter, but then we would have to keep both docstrings in sync.

Finally, it is possible to link between docstrings using cross references (e.g. in Sphinx or mkdocstrings). Firstly, this only shows up in your final HTML documentation: standard Python functions like help() don’t understand this. Secondly, it can be frustrating to read documentation that sends you to several other pages just to understand one function. In contrast, DocStrands keeps everything all in one place.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docstrands-0.1.0.tar.gz (689.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docstrands-0.1.0-py3-none-any.whl (6.1 kB view details)

Uploaded Python 3

File details

Details for the file docstrands-0.1.0.tar.gz.

File metadata

  • Download URL: docstrands-0.1.0.tar.gz
  • Upload date:
  • Size: 689.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.7

File hashes

Hashes for docstrands-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6d1445b3088065798df5550f9934aa7d91e5bbae49ad9d975c45eb63b9c48af7
MD5 bfbeb639c470cce35355b9e693744b5d
BLAKE2b-256 a01ebc3d10cf3287c1f226772be34ed0f2b9a88f8ab5af2370ebe9359afb31ab

See more details on using hashes here.

File details

Details for the file docstrands-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for docstrands-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1b291d66faaeec1f4cb67969c41d32c103460300022289c757fc24813d12cadd
MD5 104323e3eb7492965a2e7a3418e38435
BLAKE2b-256 89125bcd0482740052d844bbba6dd1c6da52b227050d871a1ea66431da46c0e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page