Module lockattrs.decorators
Provides the decorator protect. It is used to annotate the
class method __setattr__ in order to prevent attribute
modificaton.
Should be used in meta-classes and classes that are not instantiated often since the nested decorator is called every time an attribute is set.
View Source
""" Provides the decorator `protect`. It is used to annotate the
class method `__setattr__` in order to prevent attribute
modificaton.
Should be used in meta-classes and classes that are not instantiated often
since the nested decorator is called every time an attribute is set.
"""
from functools import wraps
from inspect import signature
from typing import Iterable
class ProtectedAttributeError(AttributeError):
"""Error indicating an attempted modification of a protected attribute."""
def protect(
attr_names: Iterable[str] = (),
error_type: Exception = ProtectedAttributeError,
):
"""
Function used to decorate `__setattr__`.
It raises an exception during an attempt to
modify any class attributes specified by `attr_names` after the
attributes have been initially set.
- `attr_names`: A tuple containing the names of
all class attributes that must not be modified.
The default value of `attr_names` is an empty tuple
indicating that all
attributes should be protected.
- `error_type`: Optional parameter used to
specify the type of error raised.
"""
if isinstance(attr_names, str):
attr_names = (attr_names,)
def _protect(func):
@wraps(func)
def inner(*args, **kwargs):
# Map args onto kwargs:
all_argument_names = tuple(signature(func).parameters.keys())
mapped_kwargs = kwargs.copy()
for index, arg_value in enumerate(args):
mapped_kwargs[all_argument_names[index]] = arg_value
# Check attempted modification of protected attributes.
if (
not attr_names or mapped_kwargs["name"] in attr_names
) and hasattr(mapped_kwargs["self"], mapped_kwargs["name"]):
# mapped_kwargs['name'] in mapped_kwargs['self'].__dict__:
raise error_type(
f"Class attribute '{mapped_kwargs['name']}' "
"must not be modified."
)
return func(*args, **kwargs)
return inner
return _protect
Functions
protect
def protect(
attr_names: Iterable[str] = (),
error_type: Exception = <class 'lockattrs.decorators.ProtectedAttributeError'>
)
Function used to decorate __setattr__.
It raises an exception during an attempt to
modify any class attributes specified by attr_names after the
attributes have been initially set.
attr_names: A tuple containing the names of all class attributes that must not be modified. The default value ofattr_namesis an empty tuple indicating that all attributes should be protected.error_type: Optional parameter used to specify the type of error raised.
View Source
def protect(
attr_names: Iterable[str] = (),
error_type: Exception = ProtectedAttributeError,
):
"""
Function used to decorate `__setattr__`.
It raises an exception during an attempt to
modify any class attributes specified by `attr_names` after the
attributes have been initially set.
- `attr_names`: A tuple containing the names of
all class attributes that must not be modified.
The default value of `attr_names` is an empty tuple
indicating that all
attributes should be protected.
- `error_type`: Optional parameter used to
specify the type of error raised.
"""
if isinstance(attr_names, str):
attr_names = (attr_names,)
def _protect(func):
@wraps(func)
def inner(*args, **kwargs):
# Map args onto kwargs:
all_argument_names = tuple(signature(func).parameters.keys())
mapped_kwargs = kwargs.copy()
for index, arg_value in enumerate(args):
mapped_kwargs[all_argument_names[index]] = arg_value
# Check attempted modification of protected attributes.
if (
not attr_names or mapped_kwargs["name"] in attr_names
) and hasattr(mapped_kwargs["self"], mapped_kwargs["name"]):
# mapped_kwargs['name'] in mapped_kwargs['self'].__dict__:
raise error_type(
f"Class attribute '{mapped_kwargs['name']}' "
"must not be modified."
)
return func(*args, **kwargs)
return inner
return _protect
Classes
ProtectedAttributeError
class ProtectedAttributeError(
/,
*args,
**kwargs
)
View Source
class ProtectedAttributeError(AttributeError):
"""Error indicating an attempted modification of a protected attribute."""
Ancestors (in MRO)
- builtins.AttributeError
- builtins.Exception
- builtins.BaseException
Class variables
args
Methods
with_traceback
def with_traceback(
...
)
Exception.with_traceback(tb) --
set self.traceback to tb and return self.