python - What's the proper way of defining or documenting calls handled by __getattr__? -


i have class who's job wrap class (code don't control), intercept calls wrapped class, perform logic, , pass along call underlying class. here's example:

class githubrepository(object):      def get_commit(self, sha):         return 'commit {}'.format(sha)      def get_contributors(self):         return ['bobbytables']   class logginggithubrepositorywrapper(object):      def __init__(self, github_repository):         self._github_repository = github_repository      def __getattr__(self, name):         base_func = getattr(self._github_repository, name)          def log_wrap(*args, **kwargs):             print "calling {}".format(name)             return base_func(*args, **kwargs)          return log_wrap  if __name__ == '__main__':      git_client = logginggithubrepositorywrapper(githubrepository())      print git_client.get_commit('abcdef1245')     print git_client.get_contributors() 

as can see, way implementing __getattr__ on wrapping class , delegating underlying class. downside approach users of logginggithubrepositorywrapper don't know attributes/methods underlying githubrepository has.

this leads me question: is there way define or document calls handled __getattr__? ideally, i'd able autocomplete on git_client. , provided list of supported methods. in advance!

you can few different ways, wont involve use of __getattr__.

what need dynamically create class, or @ least dynamically create wrapped functions on class. there few ways in python.

you build class definition using type() or metaclasses, or build on class instantiation using __new__ method.

every time call logginggithubrepositorywrapper(), __new__ method called. here, looks @ attributes on github_repository argument , finds non-private methods. creates function on instantiated logginggithubrepositorywrapper class instance wraps repo call in logging statement.

at end, passes modified class instance. __init__ called.

from types import methodtype   class logginggithubrepositorywrapper(object):      def __new__(cls, github_repository):         self = super(logginggithubrepositorywrapper, cls).__new__(cls)         name in dir(github_repository):             if name.startswith('__'):                 continue             func = getattr(github_repository, name)                         if isinstance(func, methodtype):                                 setattr(self, name, cls.log_wrap(func))         return self      @staticmethod     def log_wrap(func):         def wrap(*args, **kwargs):             print 'calling {0}'.format(func.__name__)             return func(*args, **kwargs)         return wrap      def __init__(self, github_repository):         ... # same 

Comments

Popular posts from this blog

java - pagination of xlsx file to XSSFworkbook using apache POI -

Unlimited choices in BASH case statement -

apache - How do I stop my index.php being run twice for every user -