Produce a method that calls either the existing method of the wrapped
    object with the same name or a special invocation if it's missing
    (see SPECIAL_METHODS in special_methods.py).

    Usage: OnAccessMutant(initial_object, callable_mutator)
    where: callable_mutator(wrapped_object) -> new_wrapped_object

def _delegate_or(smethname, func):
    """
    Produce a method that calls either the existing method of the wrapped
    object with the same name or a special invocation if it's missing
    (see SPECIAL_METHODS in special_methods.py).

    Usage: OnAccessMutant(initial_object, callable_mutator)
    where: callable_mutator(wrapped_object) -> new_wrapped_object
    """
    def delegated(self, *a, **kwa):
        # Mutate the object before access
        wrapped = object.__getattribute__(self, '__wrapped_object__')
        mutator = object.__getattribute__(self, '__wrapped_mutator__')
        wrapped = mutator(wrapped)
        object.__setattr__(self, '__wrapped_object__', wrapped)

        # Proxy access or use a fallback function
        try:
            meth = getattr(wrapped, smethname)
        except AttributeError:
            return func(wrapped, *a, **kwa)
        if not isinstance(wrapped, type):
            return meth(*a, **kwa)
        else:
            meth = getattr(type(wrapped), smethname)
            return meth(wrapped, *a, **kwa)

    return delegated