Source code for ahbicht.content_evaluation.token_logic_provider

"""
Contains a class that is able to provide any RC/FC Evaluator, HintsProvider or Package Resolver.
"""

from abc import ABC, abstractmethod
from typing import Optional, Union

from efoli import EdifactFormat, EdifactFormatVersion

from ahbicht.content_evaluation.evaluators import Evaluator
from ahbicht.content_evaluation.fc_evaluators import FcEvaluator
from ahbicht.content_evaluation.rc_evaluators import RcEvaluator
from ahbicht.expressions.hints_provider import HintsProvider
from ahbicht.expressions.package_expansion import PackageResolver


[docs] class TokenLogicProvider(ABC): """ A TokenLogicProvider is a class that can provide you with the correct evaluator/hints provider/package resolver for your use case/for any token in the parsed expression tree. """
[docs] @abstractmethod def get_rc_evaluator(self, edifact_format: EdifactFormat, format_version: EdifactFormatVersion) -> RcEvaluator: """ returns an appropriate RC Evaluator for the given edifact_format and edifact_format_version. The implementing class shall raise a NotImplementedError and not return None. """ raise NotImplementedError("The inheriting sub class has to implement this method")
[docs] @abstractmethod def get_fc_evaluator(self, edifact_format: EdifactFormat, format_version: EdifactFormatVersion) -> FcEvaluator: """ returns an appropriate FC Evaluator for the given edifact_format and edifact_format_version. The implementing class shall raise a NotImplementedError and not return None. """ raise NotImplementedError("The inheriting sub class has to implement this method")
[docs] @abstractmethod def get_hints_provider( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> HintsProvider: """ returns an appropriate HintsProvider for the given edifact_format and edifact_format_version. The implementing class shall raise a NotImplementedError and not return None. """ raise NotImplementedError("The inheriting sub class has to implement this method")
[docs] @abstractmethod def get_package_resolver( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> PackageResolver: """ Returns an appropriate PackageResolver for the given edifact_format and edifact_format_version. You can provide None as format(version) if there is only 1 package resolver available The implementing class shall raise a NotImplementedError and not return None. """ raise NotImplementedError("The inheriting sub class has to implement this method")
[docs] class SingletonTokenLogicProvider(TokenLogicProvider): """ An TokenLogicProvider that is instantiated with a list of evaluators/providers/resolvers of which the same instances will be used during the entire uptime of the application (singleton style). """ _unknown_key = "undefined" @staticmethod def _to_key(edifact_format: Optional[EdifactFormat], format_version: Optional[EdifactFormatVersion]) -> str: """ because a tuple for format and format version is not hashable / usable as key in a dict this methods converts them to a unique and hashable string """ if edifact_format is None or format_version is None: return SingletonTokenLogicProvider._unknown_key # we don't care what the key is, it just has to be unique and consistent return f"{edifact_format}-{format_version}" def __init__(self, inputs: list[Union[Evaluator, PackageResolver, HintsProvider]]) -> None: self._rc_evaluators: dict[str, RcEvaluator] = {} self._fc_evaluators: dict[str, FcEvaluator] = {} self._hints_providers: dict[str, HintsProvider] = {} self._package_resolvers: dict[str, PackageResolver] = {} for instance in inputs: key: str try: key = SingletonTokenLogicProvider._to_key(instance.edifact_format, instance.edifact_format_version) except NotImplementedError: # this is ok, if there's only one of the kind (e.g. only one package resolver, only one hints provider) # if the user tries to provide more than 1 instance of the same kind without specifying format(version) # they'll run into an value error below key = SingletonTokenLogicProvider._unknown_key target_dict: ( dict[str, RcEvaluator] | dict[str, FcEvaluator] | dict[str, HintsProvider] | dict[str, PackageResolver] ) if isinstance(instance, RcEvaluator): target_dict = self._rc_evaluators elif isinstance(instance, FcEvaluator): target_dict = self._fc_evaluators elif isinstance(instance, HintsProvider): target_dict = self._hints_providers elif isinstance(instance, PackageResolver): target_dict = self._package_resolvers else: raise ValueError(f"The type of '{instance}' is not supported. Expected either RC or FC evaluator") if key in target_dict: conflict = target_dict[key] raise ValueError( f"The key '{key}' is already used by {conflict}. For this reason you cannot add '{instance}'" ) target_dict[key] = instance # type: ignore[assignment]
[docs] def get_fc_evaluator( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> FcEvaluator: try: return self._fc_evaluators[SingletonTokenLogicProvider._to_key(edifact_format, format_version)] except KeyError as key_error: raise NotImplementedError( f"No FC Evaluator has been registered for {edifact_format} in {format_version}" ) from key_error
[docs] def get_rc_evaluator( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> RcEvaluator: try: return self._rc_evaluators[SingletonTokenLogicProvider._to_key(edifact_format, format_version)] except KeyError as key_error: raise NotImplementedError( f"No RC Evaluator has been registered for {edifact_format} in {format_version}" ) from key_error
[docs] def get_hints_provider( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> HintsProvider: try: return self._hints_providers[SingletonTokenLogicProvider._to_key(edifact_format, format_version)] except KeyError as key_error: raise NotImplementedError( f"No HintsProvider has been registered for {edifact_format} in {format_version}" ) from key_error
[docs] def get_package_resolver( self, edifact_format: Optional[EdifactFormat] = None, format_version: Optional[EdifactFormatVersion] = None ) -> PackageResolver: try: return self._package_resolvers[SingletonTokenLogicProvider._to_key(edifact_format, format_version)] except KeyError as key_error: raise NotImplementedError( f"No PackageResolver has been registered for {edifact_format} in {format_version}" ) from key_error