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

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -