Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • toejough/din
1 result
Show changes
Commits on Source (4)
# python
__pycache__
*.egg-info
build
dist
# static checking
.coverage
......
# 0.1.0 - initial release
## Major Updates
* added equality mixin for standard equality checks
* added repr mixin for better default reprs
# 0.2.0 - frozen
## Minor Updates
* added a frozen mixin
......@@ -287,3 +287,24 @@ class ReprMixin:
def __repr__(self) -> str:
# the repr ID dict is meant to track per repr call.
return _ReprFormatter().format_obj(self, indent=self._repr_indent)
class FrozenMixin:
"""
A mixin to freeze an object.
Only freezes the object's attributes themselves, not any
mutability within those attributes. For instance, you can't
say foo.my_string = 'new thing', but you can do foo.my_list.append('new thing').
"""
def __setattr__(self, name: str, value: typing.Any) -> None:
# if the caller is self.__init__, make the update
stack = inspect.stack()
caller = stack[1].frame.f_locals.get('self', None)
func = stack[1].function
if caller is self and func == '__init__':
object.__setattr__(self, name, value)
return
# else, don't
raise AttributeError(f"Can't set {name}, because {type(self).__name__} is frozen.")
......@@ -106,6 +106,11 @@ setuptools.setup(
'dev': [
'bpython==0.17.1',
],
'dist': [
'setuptools',
'wheel',
'twine',
],
},
# give your package an executable.
entry_points={
......
......@@ -578,3 +578,30 @@ def test_independent_reprs() -> None:
# the reprs are as expected
assert actual_repr == expected_repr
assert other_actual_repr == other_expected_repr
class _FrozenTestObject(din.FrozenMixin):
def __init__(self) -> None:
super().__init__()
self.my_string = 'original'
def test_frozen() -> None:
# Given
# a frozen object
frozen = _FrozenTestObject()
# an expected error
expected_message = "Can't set my_string, because _FrozenTestObject is frozen."
# When
# an attribute is set
try:
frozen.my_string = 'changed!'
except AttributeError as error:
actual_message = str(error)
# Then
# an attribute error is raised
assert expected_message == actual_message
# the value didn't change
assert frozen.my_string == 'original'
......@@ -2,7 +2,7 @@
# [ API ]
VERSION = '0.1.0'
VERSION = '0.2.0'
# [ Vulture ]
......