Commit 14047f60 authored by Hrvoje Ribicic's avatar Hrvoje Ribicic
Browse files

Make RAPI opcode attributes use a class and not a tuple



The tuple approach to storing opcode attributes might have worked when
there were four possible modifiers per method, but with aliases this
number has been pushed to five, and with forbidden parameters it will
reach six. This patch refactors it from using a tuple to using a class
with slots, and modifies all the code and tests accordingly.
Signed-off-by: default avatarHrvoje Ribicic <riba@google.com>
Reviewed-by: default avatarKlaus Aehlig <aehlig@google.com>
parent 3ea0d511
......@@ -473,10 +473,10 @@ def _GetHandlerMethods(handler):
@rtype: list of strings
"""
return sorted(method
for (method, op_attr, _, _, _) in rapi.baserlib.OPCODE_ATTRS
return sorted(m_attrs.method for m_attrs in rapi.baserlib.OPCODE_ATTRS
# Only if handler supports method
if hasattr(handler, method) or hasattr(handler, op_attr))
if hasattr(handler, m_attrs.method) or
hasattr(handler, m_attrs.opcode))
def _DescribeHandlerAccess(handler, method):
......
......@@ -51,13 +51,43 @@ _SUPPORTED_METHODS = compat.UniqueFrozenset([
])
class OpcodeAttributes(object):
"""Acts as a structure containing the per-method attribute names.
"""
__slots__ = [
"method",
"opcode",
"rename",
"aliases",
"get_input",
]
def __init__(self, method_name):
"""Initializes the opcode attributes for the given method name.
"""
self.method = method_name
self.opcode = "%s_OPCODE" % method_name
self.rename = "%s_RENAME" % method_name
self.aliases = "%s_ALIASES" % method_name
self.get_input = "Get%sOpInput" % method_name.capitalize()
def GetModifiers(self):
"""Returns the names of all the attributes that replace or modify a method.
"""
return [self.opcode, self.rename, self.aliases, self.get_input]
def GetAll(self):
return [self.method] + self.GetModifiers()
def _BuildOpcodeAttributes():
"""Builds list of attributes used for per-handler opcodes.
"""
return [(method, "%s_OPCODE" % method, "%s_RENAME" % method,
"%s_ALIASES" % method, "Get%sOpInput" % method.capitalize())
for method in _SUPPORTED_METHODS]
return [OpcodeAttributes(method) for method in _SUPPORTED_METHODS]
OPCODE_ATTRS = _BuildOpcodeAttributes()
......@@ -396,8 +426,8 @@ def GetResourceOpcodes(cls):
"""Returns all opcodes used by a resource.
"""
return frozenset(filter(None, (getattr(cls, op_attr, None)
for (_, op_attr, _, _, _) in OPCODE_ATTRS)))
return frozenset(filter(None, (getattr(cls, method_attrs.opcode, None)
for method_attrs in OPCODE_ATTRS)))
def GetHandlerAccess(handler, method):
......@@ -438,7 +468,8 @@ 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, aliases_attr, fn_attr) in OPCODE_ATTRS:
for m_attrs in OPCODE_ATTRS:
method, op_attr, rename_attr, aliases_attr, fn_attr = m_attrs.GetAll()
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
......
......@@ -108,7 +108,7 @@ class TestOpcodeResource(unittest.TestCase):
def _GetMethodAttributes(method):
attrs = ["%s_OPCODE" % method, "%s_RENAME" % method,
"%s_ALIASES" % method, "Get%sOpInput" % method.capitalize()]
assert attrs == dict((opattrs[0], list(opattrs[1:]))
assert attrs == dict((opattrs.method, opattrs.GetModifiers())
for opattrs in baserlib.OPCODE_ATTRS)[method]
return attrs
......@@ -116,8 +116,9 @@ class TestOpcodeResource(unittest.TestCase):
for method in baserlib._SUPPORTED_METHODS:
# Empty handler
obj = self._MakeClass(method, {})(None, {}, None)
for attr in itertools.chain(*baserlib.OPCODE_ATTRS):
self.assertFalse(hasattr(obj, attr))
for m_attr in baserlib.OPCODE_ATTRS:
for attr in m_attr.GetAll():
self.assertFalse(hasattr(obj, attr))
# Direct handler function
obj = self._MakeClass(method, {
......@@ -153,8 +154,9 @@ class TestOpcodeResource(unittest.TestCase):
obj = _Empty(None, {}, None)
for attr in itertools.chain(*baserlib.OPCODE_ATTRS):
self.assertFalse(hasattr(obj, attr))
for m_attr in baserlib.OPCODE_ATTRS:
for attr in m_attr.GetAll():
self.assertFalse(hasattr(obj, attr))
if __name__ == "__main__":
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment