cryostasis

This module contains function for freeze() ing python objects at the instance level, making the instance immutable. Attempted modifications to a frozen instance will result in an ImmutableError being raised. Apart from this, frozen instance will behave the same as before with no changes to their interface (freezing is not an act of wrapping). Frozen instances can be reverted to their former mutable state by thaw() ing.

exception cryostasis.ImmutableError

Error indicating that you attempted to modify a frozen instance.

class cryostasis.Exclusions(*, attrs: set[str] = <factory>, items: set[Hashable] = <factory>, bases: set[type] = <factory>, types: set[type] = <factory>, objects: set[object] = <factory>)

This class represents exclusions for the recursive functions deepfreeze() and deepthaw(). Normally those functions recurse through all attributes (except those with dunder names) and items. Sometimes it is desirable to omit certain cases from this recursion, which is possible by setting up exclusion rules in the form of an instance of this class. It provides members for exclusion rules in the following settings:

  • attrs: allows to exclude attributes based on their attribute name, i.e. the string you would pass to getattr to retrieve it.

  • items: allows exclusion of items based on their keys. This can be any hashable object for e.g. dicts and sets or integers for index-based containers like lists.

  • bases: can be used to exclude types that are a subclass of any type in bases. Note that this will only exclude types and not instances.

  • types: is used to exclude instances of certain types. Any object that would return true for an instance check with any type in this set will be excluded.

  • objects: enables exclusion of specific objects. Only the particular objects (as determined through the is operator) in this set will be excluded.

These rules can be combined freely. Any object that fits the criteria for any rule will be excluded (i.e. the checks are combined with or). Furthermore, instances of this class can be combined in the same way as set instances using the -, | and & operators.

Examples

>>> from cryostasis import Exclusions
>>> class Dummy:
...     def __init__(self):
...         my_attr = 10
...         my_list = [1, 2, 3]
...         my_dict = {"my_attr": 20, "my_list": [4, 5, 6], 2: "a"}
...         my_obj1 = object()
...         my_obj2 = object()
...         my_class = Exclusions
...
... dummy = Dummy()
>>> e1 = Exlusions(attrs={"my_attr"})  # excludes the ``my_attr`` attribute, regardless of its value but not ``"my_attr"`` in ``my_dict``".
>>> e2 = Exlusions(items={2})  # excludes ``my_list[2]``, ``my_dict[2]`` and ``my_dict["my_list"][2]``.
>>> e3 = Exlusions(bases={object})  # excludes only ``my_class`` because it is a type that is a subclass of object.
>>> e4 = Exlusions(types={list})  # excludes all list instances, in this case ``my_list`` and ``my_dict["my_list"]``.
>>> e5 = Exlusions(objects={dummy.my_obj1})  # excludes only ``my_obj1`` but not ``my_obj2`` because they are different instances.
>>>
>>> e1 | e2  # gives union of e1 and e2
Exclusions(attrs={'my_attr'}, items={2}, bases=set(), types=set(), objects=set())
>>> e1 & e2  # gives intersection between e1 and e2 (empty in this case)
Exclusions(attrs=set(), items=set(), bases=set(), types=set(), objects=set())
>>> e1 - e2  # removes rules of e2 from e1 (no changes in this case since there is no overlap)
Exclusions(attrs={'my_attr'}, items=set(), bases=set(), types=set(), objects=set())
attrs: set[str]

Set of attribute names that should be excluded (i.e. arguments to getattr)

bases: set[type]

Set of types whose subclasses should be excluded (i.e. arguments to issubclass)

items: set[Hashable]

Set of item indices that should be excluded (i.e. arguments to []-operator)

objects: set[object]

Set of specific objects that should be excluded (i.e. arguments to is operator)

types: set[type]

Set of types, whose instances should be excluded (i.e. arguments to isinstance)

cryostasis.deepfreeze(obj: Instance, *, freeze_attributes: bool = True, freeze_items: bool = True, exclusions: None | Exclusions = None) Instance

Freezes a python object and all of its attributes and items recursively, making all of them it effectively ‘immutable’. For more information, see freeze().

Parameters:
  • obj – The object to deepfreeze.

  • freeze_attributes – If True, the attributes on the instances will no longer be assignable or deletable. Defaults to True.

  • freeze_items – If True, the items (i.e. the []-operator) on the instances will no longer be assignable or deletable. Defaults to True.

  • exclusions – Instance of Exclusions that specifies rules for excluding objects from freezing. The global deepfreeze_exclusions is automatically added to the exclusions rules.

Returns:

A new reference to the deepfrozen instance. The freezing itself happens in-place. The returned reference is just for convenience.

Examples

>>> from cryostasis import deepfreeze
>>>
>>> class Dummy:
...     def __init__(self, value):
...         self.value = value
...         self.a_dict = dict(a=1, b=2, c=[])
>>>
>>> d = Dummy(value=[1,2,3])
>>> deepfreeze(d)
>>> d.value[0] = 42             # raises ImmutableError
>>> d.value = 9001              # raises ImmutableError
>>> d.a_dict['c'].append(0)     # raises ImmutableError
cryostasis.deepthaw(obj: Instance, *, exclusions: Exclusions | None = None) Instance

Undoes the freezing on an instance and all of its attributes and items recursively. The instance and any object that can be reached from its attributes or items will become mutable again afterward.

Parameters:
  • obj – The object to deep-thaw.

  • exclusions – Instance of Exclusions that specifies rules for excluding objects from thawing. By default, nothing will be excluded.

Returns:

A new reference to the deep-thawed instance. The thawing itself happens in-place. The returned reference is just for convenience.

cryostasis.freeze(obj: Instance, *, freeze_attributes: bool = True, freeze_items: bool = True) Instance

Freezes a python object, making it effectively ‘immutable’. Which aspects of the instance should be frozen can be tuned using the kw-only arguments freeze_attributes and freeze_items.

Parameters:
  • obj – The object to freeze.

  • freeze_attributes – If True, the attributes on the instance will no longer be assignable or deletable. Defaults to True.

  • freeze_items – If True, the items (i.e. the []-operator) on the instance will no longer be assignable or deletable. Defaults to True.

Returns:

A new reference to the frozen instance. The freezing itself happens in-place. The returned reference is just for convenience.

Examples

>>> from cryostasis import freeze
>>>
>>> class Dummy:
...     def __init__(self, value):
...         self.value = value
>>>
>>> d = Dummy(value=5)
>>> d.value = 42        # ok
>>> freeze(d)
>>> d.value = 9001      # raises ImmutableError
>>>
>>> l = freeze([1,2,3])
>>> l[0] = 5            #  raises ImmutableError
>>> l.append(42)        #  raises ImmutableError
cryostasis.is_frozen(obj: Instance) bool

Check that indicates whether an object is frozen or not.

Parameters:

obj – The object to check.

Returns:

True if the object is frozen, False otherwise.

cryostasis.thaw(obj: Instance) Instance

Undoes the freezing on an instance. The instance will become mutable again afterward.

Parameters:

obj – The object to make mutable again.

Returns:

A new reference to the thawed instance. The thawing itself happens in-place. The returned reference is just for convenience.

cryostasis.deepfreeze_exclusions = Exclusions(attrs=set(), items=set(), bases=set(), types={<class 'staticmethod'>, <enum 'Enum'>, <class 'classmethod'>, <class 'enum.EnumType'>, <class 'module'>}, objects={<class 'staticmethod'>, <enum 'Enum'>, <class 'classmethod'>, <class 'enum.EnumType'>})

Global exclusion rules for cryostasis.deepfreeze(). The rules are always applied in addition to the exclusions argument of cryostasis.deepfreeze().

cryostasis.warn_on_enum = True

Enums cannot be made immutable by freeze() (yet). Hence, a warning is issued when an enum is encountered. Set this variable to False to suppress the warning.