Source code for domprob.sensors.validate.vals

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Callable

from domprob.sensors.validate.base_val import (
    BaseValidator,
    ValidatorException,
)

if TYPE_CHECKING:
    from domprob.sensors.meth import (  # pragma: no cover
        BoundSensorMethod,
    )


[docs] class MissingInstrumException(ValidatorException): """Exception raised when the `instrument` parameter is missing during a call to a method. Args: method (Callable[..., Any]): The method where the missing `instrum` parameter was detected. Attributes: method (Callable[..., Any]): The method that caused the exception. Examples: >>> from domprob.sensors.validate.vals import MissingInstrumException >>> class Example: ... def method(self): ... pass ... >>> try: ... raise MissingInstrumException(Example().method) ... except MissingInstrumException as e: ... print(f"Error: {e}") ... Error: 'instrum' param missing in Example.method(...) """ def __init__(self, method: Callable[..., Any]) -> None: self.method = method super().__init__(self.msg) @property def msg(self) -> str: """Constructs a detailed error message. Returns: str: Error message indicating the missing `instrument` parameter. Examples: >>> class Example: ... def method(self): ... pass ... >>> exc = MissingInstrumException(Example().method) >>> exc.msg "'instrum' param missing in Example.method(...)" """ m_name = f"{'.'.join(self.method.__qualname__.split('.')[-2:])}(...)" return f"'instrum' param missing in {m_name}"
# pylint: disable=too-few-public-methods
[docs] class InstrumentParamExistsValidator(BaseValidator): """Validator to check if the `instrum` parameter exists. This validator raises a `MissingInstrumException` if the `instrum` parameter is `None`. Examples: >>> from domprob.sensors.validate.vals import InstrumentParamExistsValidator >>> from domprob.sensors.meth import SensorMethod >>> >>> class SomeInstrument: ... pass ... >>> class Example: ... def method(self, instrum: SomeInstrument) -> None: ... pass ... >>> meth = SensorMethod(Example.method) >>> bound_meth = meth.bind(Example()) # type: ignore >>> >>> validator = InstrumentParamExistsValidator() >>> try: ... validator.validate(bound_meth) ... except MissingInstrumException as e: ... print(f"Error: {e}") ... Error: 'instrum' param missing in Example.method(...) """
[docs] def validate(self, b_meth: BoundSensorMethod) -> None: """Validates the method to ensure the `instrument` parameter exists. Args: b_meth (BoundSensorMethod): Method with bound params to validate. Raises: MissingInstrumentException: If the `instrum` parameter is `None`. """ if b_meth.instrum is None: raise MissingInstrumException(b_meth.meth) return super().validate(b_meth)
[docs] class InstrumTypeException(ValidatorException): # pylint: disable=line-too-long """ Exception raised when the `instrum` parameter does not match the expected type. Args: b_meth (`BoundSensorMethod`): Bound method that failed validate. Attributes: method (Callable[..., Any]): The method that failed validate. instrum (Any): The invalid `instrument` instance. supp_instrums (Instruments): The supported instrument types. Examples: >>> from domprob.sensors.meth import SensorMethod >>> >>> class SomeInstrument: ... pass ... >>> class Example: ... def method(self, instrum: SomeInstrument) -> None: ... pass ... >>> meth = SensorMethod(Example.method) >>> meth.supp_instrums.record(SomeInstrument, True) Instruments(metadata=SensorMetadata(method=<function Example.method at 0x...)) >>> bound_meth = meth.bind(Example(), 'InvalidInstrument') # type: ignore >>> >>> try: ... raise InstrumTypeException(bound_meth) ... except InstrumTypeException as e: ... print(f"Error: {e}") ... Error: Example.method(...) expects 'instrum' param to be one of: [SomeInstrument], but got: 'InvalidInstrument' """ def __init__(self, b_meth: BoundSensorMethod) -> None: self.method = b_meth.meth self.instrum = b_meth.instrum self.supp_instrums = b_meth.supp_instrums super().__init__(self.msg) @property def msg(self) -> str: """Constructs a detailed error message. Returns: str: Error message describing the invalid `instrument`. """ instrum_names = (i.__name__ for i, _ in self.supp_instrums) m_name = f"{'.'.join(self.method.__qualname__.split('.')[-2:])}(...)" return ( f"{m_name} expects 'instrum' param to be one of: " f"[{', '.join(instrum_names)}], but got: {self.instrum!r}" )
# pylint: disable=too-few-public-methods
[docs] class InstrumentTypeValidator(BaseValidator): # pylint: disable=line-too-long """Validator to check if the `instrum` is of a valid type. This validator raises an `InstrumTypeException` if the type of the `instrum` parameter is not one of the supported instrument types. Examples: >>> from domprob.sensors.validate.vals import InstrumentTypeValidator >>> from domprob.sensors.meth import SensorMethod >>> class MockInstrument: ... pass ... >>> class Example: ... def method(self, instrum: MockInstrument) -> None: ... pass ... >>> meth = SensorMethod(Example.method) >>> bound_meth = meth.bind(Example(), 'InvalidInstrument') # type: ignore >>> >>> validator = InstrumentTypeValidator() >>> try: ... validator.validate(bound_meth) ... except InstrumTypeException as e: ... print(f"Error: {e}") ... Error: Example.method(...) expects 'instrum' param to be one of: [], but got: 'InvalidInstrument' """
[docs] def validate(self, b_meth: BoundSensorMethod) -> None: """Validates the method by checking the type of the `instrument` parameter. Args: b_meth (`BoundSensorMethod`): Method with bound params to validate. Raises: InstrumTypeException: If the `instrum` parameter is not an instance of any specified instrument classes. """ for supp_instrum, _ in b_meth.supp_instrums: # pylint: disable=unidiomatic-typecheck if type(b_meth.instrum) is supp_instrum: return super().validate(b_meth) raise InstrumTypeException(b_meth)
[docs] class NoSupportedInstrumsException(ValidatorException): """Exception raised when no supported instruments are defined for a method. This exception indicates that the method's metadata does not include any supported instrument types, which is required for proper validate. Args: method (Callable[..., Any]): The method where the missing supported instruments were detected. Attributes: method (Callable[..., Any]): The method that caused the exception. Examples: >>> from domprob.sensors.validate.vals import NoSupportedInstrumsException >>> class Example: ... def method(self): ... pass ... >>> try: ... raise NoSupportedInstrumsException(Example().method) ... except NoSupportedInstrumsException as e: ... print(f"Error: {e}") ... Error: Example.method(...) has no supported instrument types defined """ def __init__(self, method: Callable[..., Any]) -> None: self.method = method super().__init__(self.msg) @property def msg(self) -> str: """ Constructs a detailed error message. Returns: str: Error message indicating that no supported instrument types are defined for the method. Examples: >>> class Example: ... def method(self): ... pass ... >>> exc = NoSupportedInstrumsException(Example().method) >>> exc.msg 'Example.method(...) has no supported instrument types defined' """ m_name = f"{'.'.join(self.method.__qualname__.split('.')[-2:])}(...)" return f"{m_name} has no supported instrument types defined"
# pylint: disable=too-few-public-methods
[docs] class SupportedInstrumentsExistValidator(BaseValidator): # pylint: disable=line-too-long """Validator to ensure that at least one supported instrument is defined. This validator raises a `NoSupportedInstrumentsException` if the method's metadata does not include any supported instrument types. Examples: >>> from domprob.sensors.validate.vals import SupportedInstrumentsExistValidator >>> from domprob.sensors.meth import SensorMethod >>> class Example: ... def method(self, instrument: Any) -> None: ... pass ... >>> meth = SensorMethod(Example.method) >>> bound_meth = meth.bind(Example()) >>> >>> validator = SupportedInstrumentsExistValidator() >>> try: ... validator.validate(bound_meth) ... except NoSupportedInstrumsException as e: ... print(f"Error: {e}") ... Error: Example.method(...) has no supported instrument types defined """
[docs] def validate(self, b_meth: BoundSensorMethod) -> None: """Validates the method by checking the type of the `instrument` parameter. Args: b_meth (`BoundSensorMethod`): Method with bound params to validate. Raises: NoSupportedInstrumsException: If the `instrum` parameter is not an instance of any valid instrument classes. """ if not b_meth.supp_instrums: raise NoSupportedInstrumsException(b_meth.meth) return super().validate(b_meth)