def monkeypatch_method(cls, fname=None):
    """
    Monkey-patches some method, replacing it with another
    implementation. Original method is preserved on ``.orig``
    attribute.

    >>> class SomeClass(object):
    ...    def meth(self, arg):
    ...        return "Original: " + arg
    >>>
    >>> @monkeypatch_method(SomeClass)
    ... def meth(self, arg):
    ...     return "Patched: " + meth.orig(self, arg)
    >>>
    >>> obj = SomeClass()
    >>> print obj.meth("some param")
    Patched: Original: some param

    It is also possible to use different name

    >>> class SomeClass(object):
    ...    def meth(self, arg):
    ...        return "Original: " + arg
    >>>
    >>> @monkeypatch_method(SomeClass, "meth")
    ... def another_meth(self, arg):
    ...     return "Patched: " + another_meth.orig(self, arg)
    >>>
    >>> obj = SomeClass()
    >>> print obj.meth("some param")
    Patched: Original: some param

    :param cls: Class being modified
    :param fname: Name of method being monkey-patched (if not given,
           name of decorated function is used)
    """
    def decorator(func):
        local_fname = fname
        if local_fname is None:
            local_fname = func.__name__
        setattr(func, "orig", getattr(cls, local_fname, None))
        setattr(cls, local_fname, func)
        return func
    return decorator