From 5f026cd752a234d9624fe9572cf397b6ea4a74b0 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Feb 25 2020 09:25:05 +0000 Subject: PR#1987: Add doc string for virtual methods Merges #1987 https://pagure.io/koji/pull-request/1987 Fixes: #1533 https://pagure.io/koji/issue/1533 Add doc string for virtual methods --- diff --git a/koji/__init__.py b/koji/__init__.py index 923d8a6..1ddf48b 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -2178,14 +2178,44 @@ class VirtualMethod(object): # some magic to bind an XML-RPC method to an RPC server. # supports "nested" methods (e.g. examples.getStateName) # supports named arguments (if server does) - def __init__(self, func, name): + def __init__(self, func, name, session=None): self.__func = func self.__name = name + self.__session = session + def __getattr__(self, name): return type(self)(self.__func, "%s.%s" % (self.__name, name)) + def __call__(self, *args, **opts): return self.__func(self.__name, args, opts) + @property + def __doc__(self): + if self.__session is None: + # There could be potentially session-less object + return None + # try to fetch API docs + if self.__session._apidoc is None: + try: + self.__session._apidoc = dict( + [(f["name"], f) for f in self.__func("_listapi", [], {})] + ) + except: + self.__session._apidoc = {} + + funcdoc = self.__session._apidoc.get(self.__name) + if funcdoc: + # add argument description to docstring since the + # call signature is not updated, yet + argdesc = funcdoc["name"] + funcdoc["argdesc"] + "\n" + doc = funcdoc["doc"] + if doc: + return argdesc + doc + else: + return argdesc + else: + return None + def grab_session_options(options): """Convert optparse options to a dict that ClientSession can handle; @@ -2232,6 +2262,7 @@ class ClientSession(object): opts = {} else: opts = opts.copy() + self._apidoc = None self.baseurl = baseurl self.opts = opts self.authtype = None @@ -2796,7 +2827,9 @@ class ClientSession(object): def __getattr__(self, name): #if name[:1] == '_': # raise AttributeError("no attribute %r" % name) - return VirtualMethod(self._callMethod, name) + if name == '_apidoc': + return self.__dict__['_apidoc'] + return VirtualMethod(self._callMethod, name, self) def fastUpload(self, localfile, path, name=None, callback=None, blocksize=None, overwrite=False, volume=None): if blocksize is None: @@ -3055,7 +3088,7 @@ class MultiCallSession(object): self._calls = [] def __getattr__(self, name): - return VirtualMethod(self._callMethod, name) + return VirtualMethod(self._callMethod, name, self._session) def _callMethod(self, name, args, kwargs=None, retry=True): """Add a new call to the multicall"""