Skip to content

Reference class

ReferenceClass

Class whose attributes can by references to other attributes

Source code in quam/utils/reference_class.py
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
class ReferenceClass:
    """Class whose attributes can by references to other attributes"""

    _initialized: ClassVar[bool] = False

    def __post_init__(self) -> None:
        """Post init function"""
        self._initialized = True

    def _get_referenced_value(self, attr: str) -> Any:
        """Get the value of an attribute by reference

        This function should generally be overwritten by subclasses
        """
        raise NotImplementedError

    def _is_reference(self, attr: str) -> bool:
        """Check if an attribute is a reference

        This function should generally be overwritten by subclasses
        """
        raise NotImplementedError

    def get_unreferenced_value(self, attr: str) -> Any:
        """Get the raw value of an attribute, returning the reference if it is one"""
        return super().__getattribute__(attr)

    def __getattribute__(self, attr: str) -> Any:
        attr_val = super().__getattribute__(attr)

        if attr in ["_is_reference", "_get_referenced_value", "__post_init__"]:
            return attr_val

        try:
            if self._is_reference(attr_val):
                return self._get_referenced_value(attr_val)
            return attr_val
        except Exception:
            return attr_val

    def _is_valid_setattr(
        self, attr: str, value: Any, error_on_False: bool = False
    ) -> bool:
        """Check if an attribute can be set to a value

        This will be called by __setattr__ to check if the attribute can be set to the
        given value.

        Args:
            attr: The attribute to set
            value: The value to set the attribute to
            error_on_False: If True, raise an error if the attribute cannot be set to
                the value. If False, return False if the attribute cannot be set to the
                value.

        Returns:
            True if
            - The new value is None
            - The attribute does not exist yet
            - The attribute's previous value is not a reference
            - The new value is a reference
            False otherwise, in particular if the previous value is a reference and the
            new value is not and is also not None.

        Raises:
            ValueError: If error_on_False is True and the attribute cannot be set to
                the value.
        """
        if value is None:
            return True

        try:
            original_value = self.get_unreferenced_value(attr)
        except AttributeError:
            return True

        if not self._initialized:
            return True

        if self._is_reference(original_value):
            if self._is_reference(value):
                return True

            if not error_on_False:
                return False

            raise ValueError(
                f"Cannot set attribute {attr} to {value} because it is a reference. "
                "To overwrite the reference, set the attribute to None first.\n"
                f"Object: {self}\n"
                f"Original value: {original_value}"
            )

        return True

    def __setattr__(self, attr: str, value: Any) -> None:
        self._is_valid_setattr(attr, value, error_on_False=True)

        super().__setattr__(attr, value)

__post_init__()

Post init function

Source code in quam/utils/reference_class.py
12
13
14
def __post_init__(self) -> None:
    """Post init function"""
    self._initialized = True

_get_referenced_value(attr)

Get the value of an attribute by reference

This function should generally be overwritten by subclasses

Source code in quam/utils/reference_class.py
16
17
18
19
20
21
def _get_referenced_value(self, attr: str) -> Any:
    """Get the value of an attribute by reference

    This function should generally be overwritten by subclasses
    """
    raise NotImplementedError

_is_reference(attr)

Check if an attribute is a reference

This function should generally be overwritten by subclasses

Source code in quam/utils/reference_class.py
23
24
25
26
27
28
def _is_reference(self, attr: str) -> bool:
    """Check if an attribute is a reference

    This function should generally be overwritten by subclasses
    """
    raise NotImplementedError

_is_valid_setattr(attr, value, error_on_False=False)

Check if an attribute can be set to a value

This will be called by setattr to check if the attribute can be set to the given value.

Parameters:

Name Type Description Default
attr str

The attribute to set

required
value Any

The value to set the attribute to

required
error_on_False bool

If True, raise an error if the attribute cannot be set to the value. If False, return False if the attribute cannot be set to the value.

False

Returns:

Type Description
bool

True if

bool
  • The new value is None
bool
  • The attribute does not exist yet
bool
  • The attribute's previous value is not a reference
bool
  • The new value is a reference
bool

False otherwise, in particular if the previous value is a reference and the

bool

new value is not and is also not None.

Raises:

Type Description
ValueError

If error_on_False is True and the attribute cannot be set to the value.

Source code in quam/utils/reference_class.py
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def _is_valid_setattr(
    self, attr: str, value: Any, error_on_False: bool = False
) -> bool:
    """Check if an attribute can be set to a value

    This will be called by __setattr__ to check if the attribute can be set to the
    given value.

    Args:
        attr: The attribute to set
        value: The value to set the attribute to
        error_on_False: If True, raise an error if the attribute cannot be set to
            the value. If False, return False if the attribute cannot be set to the
            value.

    Returns:
        True if
        - The new value is None
        - The attribute does not exist yet
        - The attribute's previous value is not a reference
        - The new value is a reference
        False otherwise, in particular if the previous value is a reference and the
        new value is not and is also not None.

    Raises:
        ValueError: If error_on_False is True and the attribute cannot be set to
            the value.
    """
    if value is None:
        return True

    try:
        original_value = self.get_unreferenced_value(attr)
    except AttributeError:
        return True

    if not self._initialized:
        return True

    if self._is_reference(original_value):
        if self._is_reference(value):
            return True

        if not error_on_False:
            return False

        raise ValueError(
            f"Cannot set attribute {attr} to {value} because it is a reference. "
            "To overwrite the reference, set the attribute to None first.\n"
            f"Object: {self}\n"
            f"Original value: {original_value}"
        )

    return True

get_unreferenced_value(attr)

Get the raw value of an attribute, returning the reference if it is one

Source code in quam/utils/reference_class.py
30
31
32
def get_unreferenced_value(self, attr: str) -> Any:
    """Get the raw value of an attribute, returning the reference if it is one"""
    return super().__getattribute__(attr)