Source code for pydoit_nb.attrs_helpers
"""
Tools for helping with :mod:`attrs`, particularly validators
TODO: move this into its own package and check with attrs developers
if they want something like this in their package
"""
from __future__ import annotations
from functools import wraps
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Any, Callable, TypeVar
import attr
T = TypeVar("T")
[docs]class AttributeInitialisationError(ValueError):
"""
Raised when there is an issue while initialising an :obj:`attr.Attribute`
"""
def __init__(
self,
instance: Any,
attribute: attr.Attribute[Any],
value: T,
) -> None:
"""
Initialise the error
Parameters
----------
instance
Instance being initialised
attribute
Attribute being set
value
Value being used to set the attribute
"""
error_msg = (
"Error raised while initialising attribute "
f"``{attribute.name}`` of ``{type(instance)}``. "
f"Value provided: {value}"
)
super().__init__(error_msg)
[docs]def add_attrs_context(
original: Callable[[Any, attr.Attribute[Any], T], None],
) -> Callable[[Any, attr.Attribute[Any], T], None]:
"""
Decorate function with a ``try...except`` to add the :mod:`attrs` context
This means that the information about what attribute was being set and
what value it was passed is also shown to the user
Parameters
----------
original
Function to decorate
Returns
-------
Decorated function
Notes
-----
Only works with Python 3.11 and above. For other Python versions, the raw
error is simply shown instead
"""
@wraps(original)
def with_attrs_context(
instance: Any,
attribute: attr.Attribute[Any],
value: T,
) -> None:
try:
original(instance, attribute, value)
except Exception as exc:
raise AttributeInitialisationError(instance=instance, attribute=attribute, value=value) from exc
return with_attrs_context