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.lang.registry import Registry, Component
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