def intercept(obj, methodname, wrapper):
original = getattr(obj, methodname)<EOL>def replacement(*args, **kwargs):<EOL><INDENT>wrapfn = wrapper(*args, **kwargs)<EOL>wrapfn.send(None)<EOL>result = original(*args, **kwargs)<EOL>try:<EOL><INDENT>wrapfn.send(result)<EOL><DEDENT>except StopIteration:<EOL><INDENT>return result<EOL><DEDENT>else:<EOL><INDENT>raise AssertionError('<STR_LIT>')<EOL><DEDENT><DEDENT>def unwrap():<EOL><INDENT>"""<STR_LIT>"""<EOL>setattr(obj, methodname, original)<EOL><DEDENT>replacement.unwrap = unwrap<EOL>setattr(obj, methodname, replacement)<EOL>
Wraps an existing method on an object with the provided generator, which
will be "sent" the value when it yields control.

::

    >>> def ensure_primary_key_is_set():
    ...     assert model.pk is None
    ...     saved = yield
    ...     aasert model is saved
    ...     assert model.pk is not None
    ...
    >>> intercept(model, 'save', ensure_primary_key_is_set)
    >>> model.save()

:param obj: the object that has the method to be wrapped
:type obj: :class:`object`
:param methodname: the name of the method that will be wrapped
:type methodname: :class:`str`
:param wrapper: the wrapper
:type wrapper: generator callable