LGTM, thanks.
On Wed, Mar 26, 2014 at 2:25 PM, Hrvoje Ribicic <[email protected]> wrote: > This patch extends the metaclass used to generate RAPI handlers to > allow creating aliases of certain values returned by GET methods. > > Signed-off-by: Hrvoje Ribicic <[email protected]> > --- > lib/build/sphinx_ext.py | 2 +- > lib/rapi/baserlib.py | 40 > +++++++++++++++++++++++++++----- > test/py/ganeti.rapi.baserlib_unittest.py | 2 +- > 3 files changed, 36 insertions(+), 8 deletions(-) > > diff --git a/lib/build/sphinx_ext.py b/lib/build/sphinx_ext.py > index f9c71d7..5f29473 100644 > --- a/lib/build/sphinx_ext.py > +++ b/lib/build/sphinx_ext.py > @@ -473,7 +473,7 @@ def _GetHandlerMethods(handler): > > """ > return sorted(method > - for (method, op_attr, _, _) in rapi.baserlib.OPCODE_ATTRS > + for (method, op_attr, _, _, _) in > rapi.baserlib.OPCODE_ATTRS > # Only if handler supports method > if hasattr(handler, method) or hasattr(handler, op_attr)) > > diff --git a/lib/rapi/baserlib.py b/lib/rapi/baserlib.py > index f65954c..f66da64 100644 > --- a/lib/rapi/baserlib.py > +++ b/lib/rapi/baserlib.py > @@ -56,7 +56,7 @@ def _BuildOpcodeAttributes(): > > """ > return [(method, "%s_OPCODE" % method, "%s_RENAME" % method, > - "Get%sOpInput" % method.capitalize()) > + "%s_ALIASES" % method, "Get%sOpInput" % method.capitalize()) > for method in _SUPPORTED_METHODS] > > > @@ -406,7 +406,7 @@ def GetResourceOpcodes(cls): > > """ > return frozenset(filter(None, (getattr(cls, op_attr, None) > - for (_, op_attr, _, _) in OPCODE_ATTRS))) > + for (_, op_attr, _, _, _) in > OPCODE_ATTRS))) > > > def GetHandlerAccess(handler, method): > @@ -420,6 +420,22 @@ def GetHandlerAccess(handler, method): > return getattr(handler, "%s_ACCESS" % method, None) > > > +def GetHandler(get_fn, aliases): > + result = get_fn() > + if not isinstance(result, dict) or aliases is None: > + return result > + > + for (param, alias) in aliases.items(): > + if param in result: > + if alias in result: > + raise http.HttpBadRequest("Parameter '%s' has an alias of '%s', > but" > + " both values are present in response" % > + (param, alias)) > + result[alias] = result[param] > + > + return result > + > + > class _MetaOpcodeResource(type): > """Meta class for RAPI resources. > > @@ -431,13 +447,23 @@ class _MetaOpcodeResource(type): > # Access to private attributes of a client class, pylint: > disable=W0212 > obj = type.__call__(mcs, *args, **kwargs) > > - for (method, op_attr, rename_attr, fn_attr) in OPCODE_ATTRS: > + for (method, op_attr, rename_attr, aliases_attr, fn_attr) in > OPCODE_ATTRS: > if hasattr(obj, method): > - # If the method handler is already defined, "*_RENAME" or > "Get*OpInput" > - # shouldn't be (they're only used by the automatically generated > - # handler) > + # If the method handler is already defined, "*_RENAME" or > + # "Get*OpInput" shouldn't be (they're only used by the > automatically > + # generated handler) > assert not hasattr(obj, rename_attr) > assert not hasattr(obj, fn_attr) > + > + # The aliases are allowed only on GET calls > + assert not hasattr(obj, aliases_attr) or method == http.HTTP_GET > + > + # GET methods can add aliases of values they return under a > different > + # name > + if method == http.HTTP_GET and hasattr(obj, aliases_attr): > + setattr(obj, method, > + compat.partial(GetHandler, getattr(obj, method), > + getattr(obj, aliases_attr))) > else: > # Try to generate handler method on handler instance > try: > @@ -473,6 +499,8 @@ class OpcodeResource(ResourceBase): > automatically generate a GET handler submitting the opcode > @cvar GET_RENAME: Set this to rename parameters in the GET handler (see > L{baserlib.FillOpcode}) > + @cvar GET_ALIASES: Set this to duplicate return values in GET results > (see > + L{baserlib.GetHandler}) > @ivar GetGetOpInput: Define this to override the default method for > getting opcode parameters (see > L{baserlib.OpcodeResource._GetDefaultData}) > > diff --git a/test/py/ganeti.rapi.baserlib_unittest.py b/test/py/ > ganeti.rapi.baserlib_unittest.py > index c971577..6e36f23 100755 > --- a/test/py/ganeti.rapi.baserlib_unittest.py > +++ b/test/py/ganeti.rapi.baserlib_unittest.py > @@ -107,7 +107,7 @@ class TestOpcodeResource(unittest.TestCase): > @staticmethod > def _GetMethodAttributes(method): > attrs = ["%s_OPCODE" % method, "%s_RENAME" % method, > - "Get%sOpInput" % method.capitalize()] > + "%s_ALIASES" % method, "Get%sOpInput" % method.capitalize()] > assert attrs == dict((opattrs[0], list(opattrs[1:])) > for opattrs in baserlib.OPCODE_ATTRS)[method] > return attrs > -- > 1.9.1.423.g4596e3a > > -- Thomas Thrainer | Software Engineer | [email protected] | Google Germany GmbH Dienerstr. 12 80331 München Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores
