python - Call arbitrary methods on class like xmlrpclib.ServerProxy -
i have remote api accepting xmls may called like
api = xmlrpclib.serverproxy(ip) result = api.execute({"method": 'method_name', "params": [p1, p2], ... # technical values - authentication, etc })
the technical values not subject change - whole script use same values them, created class has method
def call(self, method_name, params): self.api.execute(<constructed dictionary>)
i wondering if possible call these methods directly methods of self.api
like:
self.api.method_name(params)
which in turn fill in .execute
, rest me, general idea like:
def __getattr__(self, item): if item in self.__dict__: return self.item else: return functools.partial(self.call, method_name=item)
so, if defined method in class (self.foo
, self.bar
, like) - calling produce true results of self.foo
, self.bar
.
calling self.api.method(params)
method
custom 1 works, approach "pollutes" other methods didn't define, self.api.__repr__
, like
is true according this question approach of overriding __getitem__
incorrect entirely? if - how should implement this?
i watched a talk raymond hettinger post loosely reminded of, thought i'd link it. think makes great argument approach described in post:
make api work you
first of all, don't think overriding __getattr__
sinful post might have believe.
class myapi(object): base_args = {'token': 'foobarauthtoekn'} def __init__(self, ip): self._api = serverproxy(ip) def _execute(self, method='', **kwargs): argdict = {'method': method} argdict.update(myapi2.base_args) argdict.update(kwargs) self._api.execute(argdict) def __getattr__(self, attr): return self.__dict__.get( attr, partial(self._execute, method=attr)) api = myapi('127.0.0.1') # execute({'token': ..., 'method': 'get_users', 'arg1': 'foo' ...}) = api.get_users(arg1='foo', arg2='bar') # execute({'token': ..., 'method': 'get_data', 'foo': 'stuff' ...}) = api.get_data(foo='stuff', bar='zxcv')
i because it's not lot of code, , lets use execute
in more convenient way (with keyword args), without relying on support internal api.
special behavior via metaclasses
the other approach prevents having override __getattr__
in case i've underestimated how of mistake is, , considered more pythonic, explicitly enumerate methods we'll providing our api wrapper:
class apimeta(type): def __new__(cls, clsname, bases, attrs): def exec_generic(name): base_args = {'token': 'foobarauthtoekn'} def exec_wrapper(self, params): args = {'method': name} args.update(base_args) args.update(params) return self._api.execute(args) return exec_wrapper new_attrs = { name: val if name.startswith('__') else exec_generic(name) name, val in attrs.items() } return super(apimeta, cls).__new__(cls, clsname, bases, new_attrs) class myapi(object, metaclass=apimeta): def __init__(self, ip): self._api = serverproxy(ip) def get_users(self): pass def get_data(self): pass # ...
in reality, don't this, since it's little more very convoluted way write:
class myapi(object): _base_args = {'token': 'foobarauthtoken'} def __init__(self, ip): self._api = serverproxy(ip) def get_users(self, params): argdict = {'method': 'get_users'} argdict.update(myapi._base_args) argdict.update(params) return self._api.execute(argdict) # ...
it save considerable amount of typing if have lot of methods though, , it's practice in meta-programming if you're looking or deepen understanding of python language.
here's demo both.
Comments
Post a Comment