Reflection

Jivago provides its own reflection-style registration mechanism. We will define as annotations decorators which do not alter the decorated functions or classes but add a means of programmatically inspecting said decorated functions or classes.

Accessing annotated elements is done by interrogating the Registry object. Two types of annotations are defined in Jivago :

  • Annotation: A general-purpose registering decorator.

  • ParametrizedAnnotation: Allows the passing of arguments when the annotation is used.

The Registry object contains references to all annotated elements, and provides a get_annotated_in_package method, which returns all registrations for a specific annotation, for which the package name starts with the given string. Below is an example where all classes with the @Component annotation in any package are requested.

from jivago.inject.annotation import Component
from jivago.lang.registry import Registry

registry = Registry.INSTANCE

registrations = registry.get_annotated_in_package(Component, "")

for registration in registrations:
    registered_class = registration.registered  # Registered class or function
    annotation_parameters = registration.arguments  # empty dictionary for standard annotations

Declaring Custom Annotations

Standard annotations can be defined using either the python-esque decorator-style syntax by adding the @Annotation decorator to a simple pass-through decorator, or the simpler object-style syntax by invoking the Annotation constructor.

from jivago.lang.registry import Annotation


# Decorator-style syntax
@Annotation
def MyAnnotation(x: type) -> type:
    return x


# Object-style syntax
MyAnnotation2 = Annotation()


@MyAnnotation
@MyAnnotation2
class MyAnnotatedClass(object):
    pass

Parametrized annotations can only defined using the decorator-style syntax. To create a new parametrized annotation, use the @ParametrizedAnnotation decorator on a function which returns a pass-through function. (See the example below.)

Unnamed argument will be saved in the dictionary with the declared parameter name as the key.

from jivago.lang.registry import ParametrizedAnnotation


@ParametrizedAnnotation
def MyAnnotation(param1: str, param2: str):
    return lambda x: x


@MyAnnotation(param1="foo", param2="baz")
class MyAnnotatedClass(object):
    pass