attr_utils.annotations

Add type annotations to the __init__ of an attrs class.

Since python-attrs/attrs#363 attrs has populated the __init__.__annotations__ based on the types of attributes. However, annotations were deliberately omitted when converter functions were used. This module attempts to generate the annotations for use in Sphinx documentation, even when converter functions are used, based on the following assumptions:

  • If the converter function is a Python type, such as str, int, or list, the type annotation will be that type. If the converter and the type annotation refer to the same type (e.g. list and typing.List) the type annotation will be used.

  • If the converter function has an annotation for its first argument, that annotation is used.

  • If the converter function is not annotated, the type of the attribute will be used.

The annotation can also be provided via the 'annotation' key in the metadata dict. If you prefer you can instead provide this as a keyword argument to attrib() which will construct the metadata dict and call attr.ib() for you.

Changed in version 0.2.0: Improved support for container types.

Attention

Due to changes in the typing module annotations is only officially supported on Python 3.7 and above.

Examples

Library Usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def my_converter(arg: List[Dict[str, Any]]):
    return arg


def untyped_converter(arg):
    return arg


@attr.s
class SomeClass:
    a_string: str = attr.ib(converter=str)
    custom_converter: Any = attr.ib(converter=my_converter)
    untyped: Tuple[str, int, float] = attr.ib(converter=untyped_converter)
    annotated: List[str] = attr.ib(
        converter=list,
        metadata={"annotation": Sequence[str]},
    )

add_attrs_annotations(SomeClass)

print(SomeClass.__init__.__annotations__)
# {
#   'return': None,
#   'a_string': <class 'str'>,
#   'custom_converter': typing.List[typing.Dict[str, typing.Any]],
#   'untyped': typing.Tuple[str, int, float],
#   }

Sphinx documentation:

@attr.s
class AttrsClass:
    """
    Example of using :func:`~.add_init_annotations` for attrs_ classes with Sphinx documentation.

    .. _attrs: https://www.attrs.org/en/stable/

    :param name: The name of the person.
    :param age: The age of the person.
    :param occupations: The occupation(s) of the person.
    """

    name: str = attr.ib(converter=str)
    age: int = attr.ib(converter=int)
    occupations: List[str] = attr.ib(converter=parse_occupations)

The parse_occupations function looks like:

def parse_occupations(occupations: Iterable[str]) -> Iterable[str]:  # pragma: no cover

    if isinstance(occupations, str):
        return [x.strip() for x in occupations.split(',')]
    else:
        return [str(x) for x in occupations]

The Sphinx output looks like:

class AttrsClass(name, age, occupations)[source]

Bases: object

Example of using add_init_annotations() for attrs classes with Sphinx documentation.

Parameters
  • name (str) – The name of the person.

  • age (int) – The age of the person.

  • occupations (Iterable[str]) – The occupation(s) of the person.

API Reference

Functions:

attrib(​[default, validator, repr, hash, …])

Wrapper around attr.ib() which supports the annotation keyword argument for use by add_init_annotations().

add_init_annotations(​obj)

Add type annotations to the __init__ method of an attrs class.

attr_docstring_hook(​obj)

Hook for sphinx_toolbox.more_autodoc.typehints to add annotations to the __init__ method of attrs classes.

setup(​app)

Sphinx extension to populate __init__.__annotations__ for attrs classes.

Data:

_A

Invariant TypeVar bound to typing.Any.

_C

Invariant TypeVar bound to typing.Callable.

attrib(default=NOTHING, validator=None, repr=True, hash=None, init=True, metadata=None, annotation=NOTHING, converter=None, factory=None, kw_only=False, eq=None, order=None, **kwargs)[source]

Wrapper around attr.ib() which supports the annotation keyword argument for use by add_init_annotations().

New in version 0.2.0.

Parameters
  • default – Default NOTHING.

  • validator – Default None.

  • repr (bool) – Default True.

  • hash – Default None.

  • init – Default True.

  • metadata – Default None.

  • annotation (Union[Type, object]) – The type to add to __init__.__annotations__, if different to that the type taken as input to the converter function or the type hint of the attribute. Default NOTHING.

  • converter – Default None.

  • factory – Default None.

  • kw_only (bool) – Default False.

  • eq – Default None.

  • order – Default None.

See the documentation for attr.ib() for descriptions of the other arguments.

_A = TypeVar(_A, bound=typing.Any)

Type:    TypeVar

Invariant TypeVar bound to typing.Any.

_C = TypeVar(_C, bound=typing.Callable)

Type:    TypeVar

Invariant TypeVar bound to typing.Callable.

add_init_annotations(obj)[source]

Add type annotations to the __init__ method of an attrs class.

Return type

~_C

attr_docstring_hook(obj)[source]

Hook for sphinx_toolbox.more_autodoc.typehints to add annotations to the __init__ method of attrs classes.

Parameters

obj (~_A) – The object being documented.

Return type

~_A

setup(app)[source]

Sphinx extension to populate __init__.__annotations__ for attrs classes.

Parameters

app (Sphinx)

Return type

SphinxExtMetadata