Skip to content

rats.annotations


rats.annotations

General purpose library to attach annotations to functions.

Annotations are typically, but not exclusively, attached using decorators.

DecoratorType = TypeVar('DecoratorType', bound=Callable[..., Any]) module-attribute

T_GroupType = TypeVar('T_GroupType', bound=NamedTuple) module-attribute

__all__ = ['AnnotationsContainer', 'DecoratorType', 'GroupAnnotations', 'T_GroupType', 'annotation', 'get_annotations', 'get_class_annotations'] module-attribute

AnnotationsContainer

Bases: NamedTuple

Holds metadata about the annotated functions or class methods.

Loosely inspired by: https://peps.python.org/pep-3107/.

annotations instance-attribute

empty() staticmethod

Source code in rats/annotations/_functions.py
@staticmethod
def empty() -> "AnnotationsContainer":
    return AnnotationsContainer(annotations=())

with_group(namespace, group_id)

Source code in rats/annotations/_functions.py
def with_group(
    self,
    namespace: str,
    group_id: NamedTuple,
) -> "AnnotationsContainer":
    return AnnotationsContainer(
        annotations=tuple(
            [
                annotation_group
                for x in self.with_namespace(namespace)
                for annotation_group in x
                if group_id in annotation_group.groups
            ]
        ),
    )

with_namespace(namespace)

Source code in rats/annotations/_functions.py
def with_namespace(
    self,
    namespace: str,
) -> "AnnotationsContainer":
    return AnnotationsContainer(
        annotations=tuple([x for x in self.annotations if x.namespace == namespace]),
    )

GroupAnnotations

Bases: ExtNamedTuple, Generic[T_GroupType]

The list of T_GroupType objects identified by a given name in a namespace.

groups instance-attribute

name instance-attribute

The name of the annotation, typically the name of the function in a class

namespace instance-attribute

All the groups in a namespace are expected to be of the same T_GroupType.

annotation(namespace, group_id)

Decorator to add an annotation to a function.

Typically used to create domain-specific annotation functions for things like DI Containers. For examples, see the rats.apps annotations, like service() and group().

Source code in rats/annotations/_functions.py
def annotation(
    namespace: str,
    group_id: NamedTuple,
) -> Callable[[DecoratorType], DecoratorType]:
    """
    Decorator to add an annotation to a function.

    Typically used to create domain-specific annotation functions for things like DI Containers.
    For examples, see the rats.apps annotations, like service() and group().
    """

    def decorator(fn: DecoratorType) -> DecoratorType:
        if not hasattr(fn, "__rats_annotations__"):
            fn.__rats_annotations__ = AnnotationsBuilder()  # type: ignore[reportFunctionMemberAccess]

        fn.__rats_annotations__.add(namespace, group_id)  # type: ignore[reportFunctionMemberAccess]

        return fn

    return decorator

get_annotations(fn)

Get all annotations for a function or class method.

Builds an instance of AnnotationsContainer from the annotations found in the object's "rats_annotations" attribute.

Source code in rats/annotations/_functions.py
def get_annotations(fn: Callable[..., Any]) -> AnnotationsContainer:
    """
    Get all annotations for a function or class method.

    Builds an instance of AnnotationsContainer from the annotations found in the object's
    "__rats_annotations__" attribute.
    """
    builder: AnnotationsBuilder = getattr(
        fn,
        "__rats_annotations__",
        AnnotationsBuilder(),
    )

    return builder.make(fn.__name__)

get_class_annotations(cls) cached

Get all annotations for a class.

Traverses the class methods looking for any annotated with "rats_annotations" and returns an instance of AnnotationsContainer. This function tries to cache the results to avoid any expensive parsing of the class methods.

Source code in rats/annotations/_functions.py
@cache
def get_class_annotations(cls: type) -> AnnotationsContainer:
    """
    Get all annotations for a class.

    Traverses the class methods looking for any annotated with "__rats_annotations__" and returns
    an instance of AnnotationsContainer. This function tries to cache the results to avoid any
    expensive parsing of the class methods.
    """
    tates: list[GroupAnnotations[Any]] = []

    for method_name in dir(cls):
        method = getattr(cls, method_name)
        if not hasattr(method, "__rats_annotations__"):
            continue

        builder: AnnotationsBuilder = method.__rats_annotations__
        tates.extend(builder.make(method_name).annotations)

    return AnnotationsContainer(annotations=tuple(tates))