[Tutor] monkey patching question
Albert-Jan Roskam
fomcl at yahoo.com
Tue Feb 17 22:53:18 CET 2015
Hi,
I would like to monkey patch a function 'decode' that is defined inside a class. It is defined there because it is a logical place, next to its counterpart *method* 'encode'. I can successfully monkey patch meth1, but when I call meth2, it does not use the patched decorator. How can this be done? In this example, I would like to effectively "turn off" @decode. I am hoping for a solution that works on Python 2.7 and 3.3+.
import inspect, functools
class Foo(object):
def decode(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print "original decorator was called"
return func(*args, **kwargs).decode("utf-8")
return wrapped
def encode(self):
"""this is just here to show why decode() is defined
within Foo"""
pass
def meth1(self):
return "original method was called"
@decode
def meth2(self):
return b"python rocks"
# ---- works -----
f = Foo()
print f.meth1()
Foo.meth1 = lambda self: "new method was called"
print f.meth1()
print "-------------------"
# ---- does not work -----
def patched_decode(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print "patched decorator was called"
return func(*args, **kwargs)
return wrapped
f = Foo()
print 'ORIGINAL'
print inspect.getsource(Foo.decode) # shows source code of regular decode (as expected)
result = f.meth2()
print repr(result), type(result)
#setattr(Foo, "decode", patched_decode)
Foo.decode = patched_decode
print 'PATCHED'
print inspect.getsource(f.decode) # shows source code of patched_decode (as expected)
result = f.meth2()
print repr(result), type(result) # not patched at all! it's still unicode!
##### output:
In [1]: %run monkey_patch.py
original method was called
new method was called
-------------------
ORIGINAL
def decode(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print "original decorator was called"
return func(*args, **kwargs).decode("utf-8")
return wrapped
original decorator was called
u'python rocks' <type 'unicode'>
PATCHED
def patched_decode(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print "patched decorator was called"
return func(*args, **kwargs)
return wrapped
original decorator was called
u'python rocks' <type 'unicode'>
Regards,
Albert-Jan
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a
fresh water system, and public health, what have the Romans ever done for us?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More information about the Tutor
mailing list