The subscribers module contains a subscriber for "enforcing" freezing
using zope.locking tokens.  This, of course, assumes that zope.locking
tokens are configured to themselves be enforced somehow, using
approaches such as those in zc.tokenpolicy.  By default, this `freezer`
subscriber is registered only for objects that provide
zc.freeze.interfaces.ITokenEnforced.  Imagine a demo object that
implements ITokenEnforced, with a token utility already in place [#setup]_.

    >>> import zc.freeze.subscribers
    >>> import zope.component
    >>> zope.component.provideHandler(zc.freeze.subscribers.freezer)
    >>> demo = Demo()
    >>> import zc.freeze.interfaces
    >>> import zope.interface
    >>> zope.interface.directlyProvides(
    ...     demo, zc.freeze.interfaces.ITokenEnforced)
    >>> zc.freeze.interfaces.ITokenEnforced.providedBy(demo)
    True
    >>> util.get(demo) is None
    True
    >>> demo._z_frozen
    False
    >>> demo._z_freeze()
    >>> demo._z_frozen
    True
    >>> import zope.locking.interfaces
    >>> zope.locking.interfaces.IFreeze.providedBy(util.get(demo))
    True

If an object does not provide ITokenEnforced, the subscriber will not
fire, given a default registration.

    >>> demo2 = Demo()
    >>> zc.freeze.interfaces.ITokenEnforced.providedBy(demo2)
    False
    >>> demo2._z_freeze()
    >>> demo2._z_frozen
    True
    >>> util.get(demo2) is None
    True

=========
Footnotes
=========

.. [#setup] This sets up a zope.locking token utility as a global,
    non-persistent utility.  This is completely useless and even dangerous
    in real use, but is fine for this test.  This code also creates a Demo
    class that provides IVersioning and can be used in our non-persistent
    setup.

    >>> from zope import interface, component
    >>> from zope.locking import utility, interfaces
    >>> util = utility.TokenUtility()
    >>> component.provideUtility(util, provides=interfaces.ITokenUtility)
    >>> import zope.app.keyreference.interfaces
    >>> class IDemo(interface.Interface):
    ...     """a demonstration interface for a demonstration class"""
    ...
    >>> import zc.freeze
    >>> class Demo(zc.freeze.Freezing):
    ...     interface.implements(IDemo)
    ...
    >>> class DemoKeyReference(object):
    ...     component.adapts(IDemo)
    ...     _class_counter = 0
    ...     interface.implements(
    ...         zope.app.keyreference.interfaces.IKeyReference)
    ...     def __init__(self, context):
    ...         self.context = context
    ...         class_ = type(self)
    ...         self._id = getattr(context, '__demo_key_reference__', None)
    ...         if self._id is None:
    ...             self._id = class_._class_counter
    ...             context.__demo_key_reference__ = self._id
    ...             class_._class_counter += 1
    ...     key_type_id = 'zc.freeze.DemoKeyReference'
    ...     def __call__(self):
    ...         return self.context
    ...     def __hash__(self):
    ...         return (self.key_type_id, self._id)
    ...     def __cmp__(self, other):
    ...         if self.key_type_id == other.key_type_id:
    ...             return cmp(self._id, other._id)
    ...         return cmp(self.key_type_id, other.key_type_id) 
    ...
    >>> component.provideAdapter(DemoKeyReference)
