I am trying to create a generic Python class for a Pub/Sub type app, where the model definition specified three methods for each type of resource X that we have:
new_X
changed_X
deleted_X
I've abstracted the code to a single method, that accepts parameters about the type and action:
def _pub_wrapper(self, verb, obj_type, id_list):
ids = [str(i) for i in id_list]
self._pub(ids, '{0}.{1}'.format(verb,
obj_type.lower()))
But this then requires me to hand-write each of the defined methods, albeit in one line, each:
def new_resources(self, id_list):
self._pub_wrapper('new', 'resources', id_list)
def changed_resources(self, id_list):
self._pub_wrapper('changed', 'resources', id_list)
I'm trying to find a better pattern, to abstract this even further, so that I don't have to hand-write these one-line methods. Because the method names map to the verb / type in my pub/sub system, I was thinking of something like (pseudo-code to follow):
def __getattr__(self, item):
if name in [whitelist of approved methods]:
return ??? Some sort of partially defined version of self._pub_wrapper, with verb and obj_type filled in from parsing item ???
raise AttributeError()
This generic method would ideally catch calls like:
publisher.new_resources([])
publisher.new_items([])
publisher.new_banks([])
without me having to hand-code each of those methods...is there an elegant way to do this? I was thinking perhaps I could do it with a decorator around __getattr__
, but not quite sure how to return a decorated method. Tried the following, but the self._pub_wrapper()
method was never called.
def define_verb_and_type(*args, **kwargs):
def wrap(func):
def wrapped_func(*args):
return func(*args, verb=kwargs['verb'], obj_type=kwargs['obj_type'])
return wrapped_func
return wrap
def __getattr__(self, item):
if item in ['new_resources', 'changed_resources', 'deleted_resources']:
verb = item.split('_')[0]
obj_type = item.split('_')[-1]
return define_verb_and_type(self._pub_wrapper, verb, obj_type)
raise AttributeError