Skip to content

Instantly share code, notes, and snippets.

@dhilst
Last active September 29, 2017 14:41
Show Gist options
  • Save dhilst/cfd05839c80baa51a1a427b943add40b to your computer and use it in GitHub Desktop.
Save dhilst/cfd05839c80baa51a1a427b943add40b to your computer and use it in GitHub Desktop.
Monkey patch functions and methods proxy.
from functools import wraps
from operator import attrgetter
from importlib import import_module
from collections import Counter
import re
def packages(pfqn):
dots_n = len(pfqn.split('.'))
for i in range(dots_n):
yield pfqn.rsplit('.', i)[0]
def objgetter(pfqn):
for p in packages(pfqn):
try:
module = import_module(p)
except ImportError:
pass
else:
object_path = re.sub(r'^{}\.'.format(p), '', pfqn)
if '.' not in object_path:
parent = module
else:
parent_path = object_path.rsplit('.', 1)[0]
parent = attrgetter(parent_path)(module)
obj = attrgetter(object_path)(module)
return obj, parent
else:
raise ImportError('Cant find an importable at {}'.format(pfqn))
def proxyfunc(pfqn, target_attr):
def decorator(func):
obj, parent = objgetter(pfqn)
setattr(parent, obj.__name__, func)
setattr(func, target_attr, obj)
return func
return decorator
from pprint import pprint
p = 'foopkg.foomodule.FooClass.BarClass.barmethod'
q = 'foopkg.foomodule.foofunc'
pprint(objgetter(p))
pprint(objgetter(q))
@proxyfunc(q, 'target')
def foofunc():
return foofunc.target().upper()
@proxyfunc(p, 'target')
def barmethod(self):
return barmethod.target(self).upper()
from foopkg.foomodule import foofunc as f
print(f()) # FOO VALUE
from foopkg.foomodule import FooClass
print(FooClass.BarClass().barmethod()) # BAR VALUE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment