Source code for vak.models.decorator
"""Decorator that makes a model class,
given a definition of the model,
and another class that represents a
family of models that the new model belongs to.
The function returns a newly-created subclass
of the class representing the family of models.
The subclass can then be instantiated
and have all model methods.
"""
from __future__ import annotations
from typing import Type
from .base import Model
from .definition import validate as validate_definition
from .registry import register_model
[docs]
class ModelDefinitionValidationError(Exception):
"""Exception raised when validating a model
definition fails.
Used by :func:`vak.models.decorator.model` decorator.
"""
pass
[docs]
def model(family: Type[Model]):
"""Decorator that makes a model class,
given a definition of the model,
and another class that represents a
family of models that the new model belongs to.
Returns a newly-created subclass
of the class representing the family of models.
The subclass can then be instantiated
and have all model methods.
Parameters
----------
definition : type
The definition of the new model that will be made.
A class with all the class variables required
by :func:`vak.models.definition.validate`.
See docstring of that function for specification.
family : subclass of vak.models.Model
The class representing the family of models
that the new model will belong to.
E.g., :class:`vak.models.FrameClassificationModel`.
Returns
-------
model : type
A sub-class of ``model_family``,
with attribute ``definition``,
that will be used when making
new instances of the model.
"""
def _model(definition: Type):
if not issubclass(family, Model):
raise TypeError(
"The ``family`` argument to the ``vak.models.model`` decorator"
"should be a subclass of ``vak.models.base.Model``,"
f"but the type was: {type(family)}, "
"which was not recognized as a subclass "
"of ``vak.models.base.Model``."
)
try:
validate_definition(definition)
except ValueError as err:
raise ModelDefinitionValidationError(
f"Validation failed for the following model definition:\n{definition}"
) from err
except TypeError as err:
raise ModelDefinitionValidationError(
f"Validation failed for the following model definition:\n{definition}"
) from err
attributes = dict(family.__dict__)
attributes.update({"definition": definition})
subclass_name = definition.__name__
subclass = type(subclass_name, (family,), attributes)
subclass.__module__ = definition.__module__
# finally, add model to registry
register_model(subclass)
return subclass
return _model