def __setattr__(self, attr, value, force=False): attr_spec = self.__spec_class__.attrs.get(attr) if attr_spec: WithAttrMethod.with_attr(attr_spec, self, value, _inplace=True) return mutate_attr(self, attr=attr, value=value, inplace=True, force=force)
def with_sequence_item( attr_spec: Attr, self, _item: Any = MISSING, *, _index: Any = MISSING, _insert: bool = False, _inplace: bool = False, _if: bool = True, **attrs, ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=(attr_spec.get_collection_mutator(self, inplace=_inplace).add_item( item=_item, attrs=attrs, value_or_index=_index, by_index=True, insert=_insert, ).collection), inplace=_inplace, type_check=False, )
def transform_sequence_item( attr_spec: Attr, self, _value_or_index: Any, _transform: Callable[[Any], Any], *, _by_index: Any = MISSING, _inplace: bool = False, _if: bool = True, **attr_transforms: Dict[str, Callable[[Any], Any]], ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=(attr_spec.get_collection_mutator( self, inplace=_inplace).transform_item( value_or_index=_value_or_index, transform=_transform, by_index=_by_index, attr_transforms=attr_transforms, ).collection), inplace=_inplace, type_check=False, )
def update_sequence_item( attr_spec: Attr, self, _value_or_index: Any, _new_item: Any, *, _by_index: Any = MISSING, _inplace: bool = False, _if: bool = True, **attrs: Dict[str, Any], ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=(attr_spec.get_collection_mutator( self, inplace=_inplace).add_item( item=_new_item, attrs=attrs, value_or_index=_value_or_index, by_index=_by_index, replace=False, ).collection), inplace=_inplace, type_check=False, )
def with_mapping_item( attr_spec: Attr, self, _key: Any = None, _value: Any = None, *, _inplace: bool = False, _if: bool = True, **attrs, ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=( attr_spec.get_collection_mutator(self, inplace=_inplace) .add_item( _key, _value, attrs=attrs, ) .collection ), inplace=_inplace, type_check=False, )
def transform_mapping_item( attr_spec: Attr, self, _key: Any, _transform: Callable[[Any], Any], *, _inplace: bool = False, _if: bool = True, **attr_transforms: Dict[str, Callable[[Any], Any]], ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=( attr_spec.get_collection_mutator(self, inplace=_inplace) .transform_item( key=_key, transform=_transform, attr_transforms=attr_transforms, ) .collection ), inplace=_inplace, type_check=False, )
def update_mapping_item( attr_spec: Attr, self, _key: Any, _new_item: Any, *, _inplace: bool = False, _if: bool = True, **attrs: Dict[str, Any], ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=( attr_spec.get_collection_mutator(self, inplace=_inplace) .add_item( key=_key, value=_new_item, attrs=attrs, replace=False, require_pre_existent=True, ) .collection ), inplace=_inplace, type_check=False, )
def test_mutate_attr(): @spec_class class Item: attr: str item = Item() with pytest.raises( AttributeError, match=r"`Item\.attr` has not yet been assigned a value\."): item.attr with pytest.raises( AttributeError, match=r"`Item\.attr` has not yet been assigned a value\."): mutate_attr(item, "attr", MISSING).attr assert mutate_attr(item, "attr", "string") is not item assert mutate_attr(item, "attr", "string").attr == "string" with pytest.raises( TypeError, match="Attempt to set `Item.attr` with an invalid type"): assert mutate_attr(item, "attr", 1)
def without_set_item(attr_spec: Attr, self, _item: Any, *, _inplace: bool = False, _if: bool = True) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=(attr_spec.get_collection_mutator( self, inplace=_inplace).remove_item(_item).collection), inplace=_inplace, type_check=False, )
def with_attr( attr_spec: Attr, self, _new_value=MISSING, *, _inplace: bool = False, _if: bool = True, **attrs, ): if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=prepare_attr_value(attr_spec=attr_spec, instance=self, value=_new_value, attrs=attrs), inplace=_inplace, )
def without_sequence_item( attr_spec: Attr, self, _value_or_index: Any, *, _by_index: Any = MISSING, _inplace: bool = False, _if: bool = True, ) -> Any: if not _if: return self return mutate_attr( obj=self, attr=attr_spec.name, value=(attr_spec.get_collection_mutator( self, inplace=_inplace).remove_item( value_or_index=_value_or_index, by_index=_by_index, ).collection), inplace=_inplace, type_check=False, )
def __delattr__(self, attr, force=False): if self.__spec_class__.frozen: raise FrozenInstanceError( f"Cannot mutate attribute `{attr}` of frozen spec class `{self.__class__.__name__}`." ) attr_spec = self.__spec_class__.attrs.get(attr) if (force or not attr_spec or attr_spec.default is MISSING or attr_spec.is_masked): self.__delattr__.__raw__(self, attr) invalidate_attrs(self, attr) return None return mutate_attr( obj=self, attr=attr, value=protect_via_deepcopy( attr_spec.default), # handle default factory inplace=True, force=True, )