Skip to content
Snippets Groups Projects
switch.py 3.65 KiB
Newer Older
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from typing import Any, Callable, Dict, List, Mapping, Optional, Set, Tuple
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from odoo import api, models
from .base import ContextBuilder, Converter, Skip
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from .validate import VALIDATION_SKIP, Validator
Florent Aide's avatar
Florent Aide committed


class Switch(Converter):
    """A converter to handle switch cases.
    A list of converters are provided with a function. The first function to
    match is used, any function that is None will be used.
    The function argument is the model instance.

    Example usage:

    .. code-block:: python

        AURION_REFERENTIAL: Switch(
            [
              (
                  lambda e: e.is_xxx,
                  lambda p: "wave_code" in p,
                  Model("__wave__", {}),
              ),
              (None, None, Model("__event__", {})),
            ]
        )
Florent Aide's avatar
Florent Aide committed
    def __init__(
        self,
        converters: List[
            Tuple[
                Callable[[models.Model], bool],
                Callable[[Any], bool],
                Converter,
            ]
        ],
        validator: Optional[Validator] = None,
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        validation: str = VALIDATION_SKIP,
Florent Aide's avatar
Florent Aide committed
        context: Optional[ContextBuilder] = None,
    ):
        """
        :param converters: is a 3 tuple composed of:
        out condition, in condition, and chosen converter
        :param validator:
        :param context:
        """
Florent Aide's avatar
Florent Aide committed
        super()
        self._converters = converters
        self.context = context
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        self.validator = validator
        self.validation = validation
Florent Aide's avatar
Florent Aide committed

    def odoo_to_message(
        self, instance: models.Model, ctx: Optional[Mapping] = None
    ) -> Any:
        for out_cond, _in_cond, converter in self._converters:
            if out_cond is None or out_cond(instance):
                return converter.odoo_to_message(instance, ctx)
    def message_to_odoo(
        self,
        odoo_env: api.Environment,
        phase: str,
        message_value: Any,
        instance: models.Model,
        value_present: bool = True,
    ) -> Dict:
        for _out_cond, in_cond, converter in self._converters:
            if in_cond is None or in_cond(message_value):
                return converter.message_to_odoo(
                    odoo_env,
                    phase,
                    message_value,
                    instance,
                    value_present=value_present,
                )

        return Skip

    def is_instance_getter(self) -> bool:
        for _out_cond, _in_cond, converter in self._converters:
            if converter.is_instance_getter():
                return True

        return False

    def get_instance(self, odoo_env, message_data):
        for _out_cond, in_cond, converter in self._converters:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
            if converter.is_instance_getter() and (
                in_cond is None or in_cond(message_data)
            ):
                return converter.get_instance(odoo_env, message_data)

Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    @Converter.validator.setter
    def validator(self, value: Optional[Validator]) -> None:
        # also set validator on any converters in our switch, in case they care
        Converter.validator.fset(self, value)
        for _out_cond, _in_cond, converter in self._converters:
            converter.validator = value
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    @Converter.validation.setter
    def validation(self, value: str) -> None:
        # also set validation on any converters in our switch
        Converter.validation.fset(self, value)
        for _out_cond, _in_cond, converter in self._converters:
            converter.validation = value
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    def get__type__(self) -> Set[str]:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        for _out_cond, _in_cond, converter in self._converters:
            types.update(converter.get__type__())
        return types