Source code for quantify_scheduler.helpers.validators
# Repository: https://gitlab.com/quantify-os/quantify-scheduler
# Licensed according to the LICENCE file on the main branch
"""Module containing pydantic validators."""
from typing import Hashable
import numpy as np
from qcodes.utils import validators
from qcodes.utils.validators import Validator
from qcodes.validators.validators import numbertypes
# this is a custom qcodes Numbers validator that allows for nan values.
[docs]
class Numbers(validators.Numbers):
"""
A custom qcodes Numbers validator that allows for nan values.
Requires a number of type int, float, numpy.integer or numpy.floating.
Parameters
----------
min_value:
Minimal value allowed, default -inf.
max_value:
Maximal value allowed, default inf.
allow_nan:
if nan values are allowed, default False.
Raises
------
TypeError: If min or max value not a number. Or if min_value is
larger than the max_value.
"""
def __init__(
self,
min_value: numbertypes = -np.inf,
max_value: numbertypes = np.inf,
allow_nan: bool = False,
) -> None:
super().__init__(min_value, max_value)
[docs]
self._allow_nan = allow_nan
[docs]
def validate(self, value: numbertypes, context: str = "") -> None:
"""
Validate if number else raises error.
Parameters
----------
value:
A number.
context:
Context for validation.
Raises
------
TypeError: If not int or float.
ValueError: If number is not between the min and the max value.
"""
if not isinstance(value, self.validtypes):
raise TypeError(f"{repr(value)} is not an int or float; {context}")
if self._allow_nan and np.isnan(value):
# return early as the next statement will otherwise trigger
return
if not (self._min_value <= value <= self._max_value):
raise ValueError(
f"{repr(value)} is invalid: must be between "
f"{self._min_value} and {self._max_value} inclusive; {context}"
)
[docs]
class _Durations(Numbers):
"""Validator used for durations. It allows all numbers greater than or equal to 0."""
def __init__(
self,
) -> None:
super().__init__(min_value=0, allow_nan=False)
[docs]
class _Amplitudes(Numbers):
"""Validator used for amplitudes. It allows all numbers and nan."""
def __init__(
self,
) -> None:
super().__init__(allow_nan=True)
[docs]
class _NonNegativeFrequencies(Numbers):
"""Validator used for frequencies. It allows positive numbers and nan."""
def __init__(
self,
) -> None:
super().__init__(min_value=0, allow_nan=True)
[docs]
class _Delays(Numbers):
"""Validator used for delays. It allows all numbers."""
def __init__(
self,
) -> None:
super().__init__(allow_nan=False)
[docs]
class _Hashable(Validator[Hashable]):
"""Validator used for hashables."""
def __init__(self) -> None:
[docs]
self._valid_values = (0, "str")
[docs]
def validate(self, value: Hashable, context: str = "") -> None:
"""
Validates if hashable else raises error.
Parameters
----------
value
Value to validate
context
Context for validation.
Raises
------
TypeError
If value is not hashable.
"""
if not isinstance(value, Hashable):
raise TypeError(f"{value!r} is not Hashable; {context}")
def __repr__(self) -> str:
return "<Hashable>"