From 3825d93afeed42e62e41f743df69058511c51079 Mon Sep 17 00:00:00 2001 From: Paul Vinciguerra Date: Thu, 3 Dec 2020 21:06:28 -0500 Subject: [PATCH] papi: add support for enumflag part 1 of 2 Allow for papi to accept the new enumflag type. Change-Id: I8d8dc8fdb122e9a1b1881f5b2558635c75e4a299 Type: feature Signed-off-by: Paul Vinciguerra (cherry picked from commit 299abebe2942b4c78b85f9f3b8843f8213bf1efe) --- src/vpp-api/python/vpp_papi/__init__.py | 4 +- src/vpp-api/python/vpp_papi/tests/test_vpp_papi.py | 121 ++++++++++++++++++++- .../python/vpp_papi/tests/test_vpp_serializer.py | 5 +- src/vpp-api/python/vpp_papi/vpp_papi.py | 24 +++- src/vpp-api/python/vpp_papi/vpp_serializer.py | 25 +++-- 5 files changed, 160 insertions(+), 19 deletions(-) diff --git a/src/vpp-api/python/vpp_papi/__init__.py b/src/vpp-api/python/vpp_papi/__init__.py index e1b77811aef..c7712957b44 100644 --- a/src/vpp-api/python/vpp_papi/__init__.py +++ b/src/vpp-api/python/vpp_papi/__init__.py @@ -1,8 +1,8 @@ from .vpp_papi import FuncWrapper, VPP, VppApiDynamicMethodHolder # noqa: F401 -from .vpp_papi import VppEnum, VppEnumType # noqa: F401 +from .vpp_papi import VppEnum, VppEnumType, VppEnumFlag # noqa: F401 from .vpp_papi import VPPIOError, VPPRuntimeError, VPPValueError # noqa: F401 from .vpp_papi import VPPApiClient # noqa: F401 -from .vpp_papi import VPPApiJSONFiles # noqa: F401 +from .vpp_papi import VPPApiJSONFiles # noqa: F401 from . macaddress import MACAddress, mac_pton, mac_ntop # noqa: F401 # sorted lexicographically diff --git a/src/vpp-api/python/vpp_papi/tests/test_vpp_papi.py b/src/vpp-api/python/vpp_papi/tests/test_vpp_papi.py index 7effe68692b..99acb7c7469 100644 --- a/src/vpp-api/python/vpp_papi/tests/test_vpp_papi.py +++ b/src/vpp-api/python/vpp_papi/tests/test_vpp_papi.py @@ -23,7 +23,6 @@ from vpp_papi import vpp_transport_shmem class TestVppPapiVPPApiClient(unittest.TestCase): - def test_getcontext(self): vpp_papi.VPPApiClient.apidir = '.' c = vpp_papi.VPPApiClient(testmode=True, use_socket=True) @@ -57,7 +56,6 @@ class TestVppPapiVPPApiClientMp(unittest.TestCase): class TestVppTypes(unittest.TestCase): - def test_enum_from_json(self): json_api = """\ { @@ -114,9 +112,126 @@ class TestVppTypes(unittest.TestCase): self.assertTrue(str(t).startswith("VPPEnumType")) self.assertEqual(t.name, type_name) + def test_enumflagmixed_from_json(self): + json_api = """\ +{ + "enums": [ -class TestVppPapiLogging(unittest.TestCase): + [ + "address_family", + [ + "ADDRESS_IP4", + 0 + ], + [ + "ADDRESS_IP6", + 1 + ], + { + "enumtype": "u8" + } + ] + ], + "enumflags": [ + + [ + "if_type", + [ + "IF_API_TYPE_HARDWARE", + 0 + ], + [ + "IF_API_TYPE_SUB", + 1 + ], + [ + "IF_API_TYPE_P2P", + 2 + ], + [ + "IF_API_TYPE_PIPE", + 3 + ], + { + "enumtype": "u32" + } + ] + ] +} +""" + + processor = vpp_papi.VPPApiJSONFiles() + + # add the types to vpp_serializer + processor.process_json_str(json_api) + + vpp_transport_shmem.VppTransport = mock.MagicMock() + ac = vpp_papi.VPPApiClient(apifiles=[], testmode=True) + print(ac) + type_name = "vl_api_if_type_t" + t = ac.get_type(type_name) + print(t) + self.assertTrue(str(t).startswith("VPPEnumType")) + self.assertEqual(t.name, type_name) + + def test_enumflag_from_json(self): + json_api = """\ +{ + "enumflags": [ + [ + "address_family", + [ + "ADDRESS_IP4", + 0 + ], + [ + "ADDRESS_IP6", + 1 + ], + { + "enumtype": "u8" + } + ], + [ + "if_type", + [ + "IF_API_TYPE_HARDWARE", + 0 + ], + [ + "IF_API_TYPE_SUB", + 1 + ], + [ + "IF_API_TYPE_P2P", + 2 + ], + [ + "IF_API_TYPE_PIPE", + 3 + ], + { + "enumtype": "u32" + } + ] + ] +} +""" + processor = vpp_papi.VPPApiJSONFiles() + + # add the types to vpp_serializer + processor.process_json_str(json_api) + + vpp_transport_shmem.VppTransport = mock.MagicMock() + ac = vpp_papi.VPPApiClient(apifiles=[], testmode=True) + type_name = "vl_api_if_type_t" + t = ac.get_type(type_name) + self.assertTrue(str(t).startswith("VPPEnumType")) + self.assertEqual(t.name, type_name) + + +class TestVppPapiLogging(unittest.TestCase): def test_logger(self): class Transport: connected = True diff --git a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py index 21b23bdf6c2..c9b3d672d6a 100755 --- a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import unittest -from vpp_papi.vpp_serializer import VPPType, VPPEnumType +from vpp_papi.vpp_serializer import VPPType, VPPEnumType, VPPEnumFlagType from vpp_papi.vpp_serializer import VPPUnionType, VPPMessage from vpp_papi.vpp_serializer import VPPTypeAlias, VPPSerializerValueError from vpp_papi import MACAddress @@ -122,6 +122,9 @@ class TestAddType(unittest.TestCase): af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0], ["ADDRESS_IP6", 1], {"enumtype": "u32"}]) + aff = VPPEnumFlagType('vl_api_address_family_flag_t', [["ADDRESS_IP4", 0], + ["ADDRESS_IP6", 1], + {"enumtype": "u32"}]) ip4 = VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8', 'length': 4}) ip6 = VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8', diff --git a/src/vpp-api/python/vpp_papi/vpp_papi.py b/src/vpp-api/python/vpp_papi/vpp_papi.py index e22b88bc3f6..b4d46861832 100644 --- a/src/vpp-api/python/vpp_papi/vpp_papi.py +++ b/src/vpp-api/python/vpp_papi/vpp_papi.py @@ -31,7 +31,7 @@ import weakref import atexit import time from . vpp_format import verify_enum_hint -from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType +from . vpp_serializer import VPPType, VPPEnumType, VPPEnumFlagType, VPPUnionType from . vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias try: @@ -48,7 +48,7 @@ logger = logging.getLogger('vpp_papi') logger.addHandler(logging.NullHandler()) __all__ = ('FuncWrapper', 'VPP', 'VppApiDynamicMethodHolder', - 'VppEnum', 'VppEnumType', + 'VppEnum', 'VppEnumType', 'VppEnumFlag', 'VPPIOError', 'VPPRuntimeError', 'VPPValueError', 'VPPApiClient', ) @@ -72,6 +72,11 @@ class VppEnum: pass +@metaclass(VppEnumType) +class VppEnumFlag: + pass + + def vpp_atexit(vpp_weakref): """Clean up VPP connection on shutdown.""" vpp_instance = vpp_weakref() @@ -80,8 +85,6 @@ def vpp_atexit(vpp_weakref): vpp_instance.disconnect() - - def add_convenience_methods(): # provide convenience methods to IP[46]Address.vapi_af def _vapi_af(self): @@ -281,7 +284,12 @@ class VPPApiJSONFiles: types[t[0]] = {'type': 'enum', 'data': t} except KeyError: pass - + try: + for t in api['enumflags']: + t[0] = 'vl_api_' + t[0] + '_t' + types[t[0]] = {'type': 'enum', 'data': t} + except KeyError: + pass try: for t in api['unions']: t[0] = 'vl_api_' + t[0] + '_t' @@ -318,6 +326,12 @@ class VPPApiJSONFiles: VPPEnumType(t[0], t[1:]) except ValueError: unresolved[k] = v + if not vpp_get_type(k): + if v['type'] == 'enumflag': + try: + VPPEnumFlagType(t[0], t[1:]) + except ValueError: + unresolved[k] = v elif v['type'] == 'union': try: VPPUnionType(t[0], t[1:]) diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py index 81ce53e378d..644aeac65c6 100644 --- a/src/vpp-api/python/vpp_papi/vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py @@ -356,7 +356,10 @@ class VLAList_legacy(Packer): ) +# Will change to IntEnum after 21.04 release class VPPEnumType(Packer): + output_class = IntFlag + def __init__(self, name, msgdef, options=None): self.size = types['u32'].size self.name = name @@ -371,9 +374,9 @@ class VPPEnumType(Packer): continue ename, evalue = f e_hash[ename] = evalue - self.enum = IntFlag(name, e_hash) + self.enum = self.output_class(name, e_hash) types[name] = self - class_types[name] = VPPEnumType + class_types[name] = self.__class__ self.options = options def __getattr__(self, name): @@ -382,7 +385,6 @@ class VPPEnumType(Packer): def __bool__(self): return True - def pack(self, data, kwargs=None): if data is None: # Default to zero if not specified if self.options and 'default' in self.options: @@ -396,16 +398,23 @@ class VPPEnumType(Packer): x, size = types[self.enumtype].unpack(data, offset) return self.enum(x), size - @staticmethod - def _get_packer_with_options(f_type, options): - return VPPEnumType(f_type, types[f_type].msgdef, options=options) + @classmethod + def _get_packer_with_options(cls, f_type, options): + return cls(f_type, types[f_type].msgdef, options=options) def __repr__(self): - return "VPPEnumType(name=%s, msgdef=%s, options=%s)" % ( - self.name, self.msgdef, self.options + return "%s(name=%s, msgdef=%s, options=%s)" % ( + self.__class__.__name__, self.name, self.msgdef, self.options ) +class VPPEnumFlagType(VPPEnumType): + output_class = IntFlag + + def __init__(self, name, msgdef, options=None): + super(VPPEnumFlagType, self).__init__(name, msgdef, options) + + class VPPUnionType(Packer): def __init__(self, name, msgdef): self.name = name -- 2.16.6