[appy] appy.Hack: bugfix (patch of static methods).

This commit is contained in:
Gaetan Delannay 2015-03-14 11:26:26 +01:00
parent 93504cc0f3
commit cf0309cb26

View file

@ -65,11 +65,12 @@ class Hack:
# On this class, store m_method under its "base" name # On this class, store m_method under its "base" name
name = isStatic and method.func_name or method.im_func.__name__ name = isStatic and method.func_name or method.im_func.__name__
baseName = '_base_%s_' % name baseName = '_base_%s_' % name
if isStatic:
# If "staticmethod" isn't called hereafter, the static functions
# will be wrapped in methods.
method = staticmethod(method)
replacement = staticmethod(replacement)
setattr(klass, baseName, method) setattr(klass, baseName, method)
# Store the replacement method on klass. When doing so, even when
# m_method is static, it is wrapped in a method. This is why, in
# m_base below, when the method is static, we return method.im_func to
# retrieve the original static method.
setattr(klass, name, replacement) setattr(klass, name, replacement)
@staticmethod @staticmethod
@ -79,17 +80,21 @@ class Hack:
isStatic = klass isStatic = klass
klass = klass or method.im_class klass = klass or method.im_class
name = isStatic and method.func_name or method.im_func.__name__ name = isStatic and method.func_name or method.im_func.__name__
res = getattr(klass, '_base_%s_' % name) return getattr(klass, '_base_%s_' % name)
if isStatic: res = res.im_func
return res
@staticmethod @staticmethod
def inject(patchClass, klass, verbose=False): def inject(patchClass, klass, verbose=False):
'''Injects any method or attribute from p_patchClass into klass.''' '''Injects any method or attribute from p_patchClass into klass.'''
patched = [] patched = []
added = [] added = []
for name, attr in patchClass.__dict__.iteritems(): for name, attr in patchClass.__dict__.items():
if name.startswith('__'): continue # Ignore special methods if name.startswith('__'): continue # Ignore special methods
# Unwrap functions from static methods
if attr.__class__.__name__ == 'staticmethod':
attr = attr.__get__(attr)
static = True
else:
static = False
# Is this name already defined on p_klass ? # Is this name already defined on p_klass ?
if hasattr(klass, name): if hasattr(klass, name):
hasAttr = True hasAttr = True
@ -99,6 +104,9 @@ class Hack:
klassAttr = None klassAttr = None
if hasAttr and callable(attr) and callable(klassAttr): if hasAttr and callable(attr) and callable(klassAttr):
# Patch this method via Hack.patch # Patch this method via Hack.patch
if static:
Hack.patch(klassAttr, attr, klass)
else:
Hack.patch(klassAttr, attr) Hack.patch(klassAttr, attr)
patched.append(name) patched.append(name)
else: else: