"""freeze module
The freeze and unfreeze functions special-case some of the built-in
types. If these types grow the appropriate methods then that will
become unnecessary.
"""
__all__ = ("Freezable", "UnFreezable", "freeze", "unfreeze")
import builtins
from abc import ABCMeta, abstractmethod
class Freezable(metaclass=ABCMeta):
@abstractmethod
def __freeze__(self):
"""Returns an immutable version of this object."""
class UnFreezable(metaclass=ABCMeta):
@abstractmethod
def __unfreeze__(self):
"""Returns a mutable version of this object."""
def freeze(obj):
"""Returns the immutable version of the object."""
if hasattr(type(obj), "__freeze__"):
return obj.__freeze__()
try:
handler = _freeze_registry[type(obj)]
except KeyError:
pass
else:
return handler(obj)
#if hasattr(type(obj), "__unfreeze__"):
# return obj
msg = "Don't know how to freeze a {} object"
raise TypeError(msg.format(type(obj)))
def unfreeze(obj, strict=False):
if hasattr(type(obj), "__unfreeze__"):
return obj.__unfreeze__()
try:
handler = _unfreeze_registry[type(obj)]
except KeyError:
pass
else:
return handler(obj)
#if hasattr(type(obj), "__freeze__"):
# return obj
msg = "Don't know how to unfreeze a {} object"
raise TypeError(msg.format(type(obj)))
#################################################
# special-casing built-in types
_freeze_registry = {}
_unfreeze_registry = {}
def register(f, cls=None):
action, typename = f.__name__.split("_")
if cls is None:
cls = getattr(builtins, typename)
if action == "freeze":
_freeze_registry[cls] = f
Freezable.register(cls)
elif action == "unfreeze":
_unfreeze_registry[cls] = f
UnFreezable.register(cls)
else:
raise TypeError
return f
@register
def freeze_dict(obj):
raise NotImplementedError
@register
def unfreeze_dict(obj):
return obj
@register
def freeze_list(obj):
return tuple(obj)
@register
def unfreeze_list(obj):
return obj
@register
def freeze_tuple(obj):
return obj
@register
def unfreeze_tuple(obj):
return list(obj)