# -*- coding: utf-8 -*-
"""
flaskbb.core.changesets
~~~~~~~~~~~~~~~~~~~~~
Core interfaces for handlers, services, etc.
:copyright: (c) 2018 the FlaskBB Team
:license: BSD, see LICENSE for more details
"""
from abc import ABC, abstractmethod
from inspect import isclass
empty = None
[docs]class EmptyValue(object):
"""
Represents an empty change set value when None is a valid value
to apply to the model.
This class is a singleton.
"""
__slots__ = ()
def __new__(cls):
# hack to cut down on instances
global empty
if empty is None:
empty = super(EmptyValue, EmptyValue).__new__(cls)
return empty
def __eq__(self, other):
return isinstance(other, EmptyValue) or (
isclass(other) and issubclass(other, EmptyValue)
)
def __bool__(self):
return False
__nonzero__ = __bool__
empty = EmptyValue()
[docs]def is_empty(value, consider_none=False):
"""
Helper to check if an arbitrary value is an EmptyValue
"""
return empty == value or (consider_none and value is None)
[docs]class ChangeSetValidator(ABC):
"""
Used to validate a change set is valid to apply against a model
"""
[docs] @abstractmethod
def validate(self, model, changeset):
"""
May raise a :class:`~flaskbb.core.exceptions.ValidationError`
to signify that the changeset cannot be applied to the model.
Or a :class:`~flaskbb.core.exceptions.StopValidation` to immediately
halt all validation.
"""
pass
[docs]class ChangeSetHandler(ABC):
"""
Used to apply a changeset to a model.
"""
[docs] @abstractmethod
def apply_changeset(self, model, changeset):
"""
Receives the current model and the changeset object, apply the
changeset to the model and persist the model. May raise a
:class:`~flaskbb.core.exceptions.StopValidation` if the changeset
could not be applied.
"""
[docs]class ChangeSetPostProcessor(ABC):
"""
Used to handle actions after a change set has been persisted.
"""
[docs] @abstractmethod
def post_process_changeset(self, model, changeset):
"""
Used to react to a changeset's application to a model.
"""