From d4d633304a1c585585a0419ceb38008a9a4775ad Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Wed, 10 May 2023 13:32:56 -0400 Subject: [PATCH] Support multiple cluster codes for enums in xmls (#26476) * Support multiple cluster codes for enums in xmls * Replace 0xA with 10 for test cleanliness --- .../matter_idl/test_xml_parser.py | 67 +++++++++++++++++-- .../matter_idl/zapxml/handlers/handlers.py | 24 +++---- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/scripts/py_matter_idl/matter_idl/test_xml_parser.py b/scripts/py_matter_idl/matter_idl/test_xml_parser.py index d3ff819b37d9c7..7828c4219694fd 100755 --- a/scripts/py_matter_idl/matter_idl/test_xml_parser.py +++ b/scripts/py_matter_idl/matter_idl/test_xml_parser.py @@ -18,9 +18,6 @@ from typing import List, Union try: - from matter_idl.matter_idl_types import (AccessPrivilege, Attribute, AttributeQuality, Bitmap, Cluster, ClusterSide, Command, - ConstantEntry, DataType, Event, EventPriority, EventQuality, Field, FieldQuality, Idl, - Struct, StructQuality, StructTag) from matter_idl.zapxml import ParseSource, ParseXmls except ImportError: import os @@ -28,12 +25,12 @@ sys.path.append(os.path.abspath( os.path.join(os.path.dirname(__file__), '..'))) - - from matter_idl.matter_idl_types import (AccessPrivilege, Attribute, AttributeQuality, Bitmap, Cluster, ClusterSide, Command, - ConstantEntry, DataType, Event, EventPriority, EventQuality, Field, FieldQuality, Idl, - Struct, StructQuality, StructTag) from matter_idl.zapxml import ParseSource, ParseXmls +from matter_idl.matter_idl_types import (AccessPrivilege, Attribute, AttributeQuality, Bitmap, Cluster, ClusterSide, Command, + ConstantEntry, DataType, Enum, Event, EventPriority, EventQuality, Field, FieldQuality, + Idl, Struct, StructQuality, StructTag) + def XmlToIdl(what: Union[str, List[str]]) -> Idl: if not isinstance(what, list): @@ -223,6 +220,62 @@ def testFabricScopedAndSensitive(self): qualities=StructQuality.FABRIC_SCOPED)], )])) + def testEnum(self): + idl = XmlToIdl(''' + + Test110 + Test220 + + + + + + + + + + + + + + + + + + + ''') + e1 = Enum( + name='GlobalEnum', + base_type="ENUM8", + entries=[ + ConstantEntry(name="First", code=0), + ConstantEntry(name="Second", code=1), + ] + ) + e2 = Enum( + name='OneCluster', + base_type="ENUM8", + entries=[ + ConstantEntry(name="Three", code=3), + ] + ) + e3 = Enum( + name='TwoClusters', + base_type="ENUM8", + entries=[ + ConstantEntry(name="Big", code=100), + ConstantEntry(name="Bigger", code=2000), + ] + ) + self.assertEqual(idl, + Idl(clusters=[ + Cluster(side=ClusterSide.CLIENT, + name='Test1', code=10, enums=[e2, e3]), + Cluster(side=ClusterSide.CLIENT, + name='Test2', code=20, enums=[e3])], + enums=[e1], + )) + def testStruct(self): idl = XmlToIdl(''' diff --git a/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py b/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py index b24406c1565991..966d875c3355ed 100644 --- a/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py +++ b/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py @@ -248,7 +248,10 @@ class EnumHandler(BaseHandler, IdlPostProcessor): def __init__(self, context: Context, attrs): super().__init__(context) - self._cluster_code = None # if set, enum belongs to a specific cluster + + # no cluster codes means global. Note that at the time + # of writing this, no global enums were defined in XMLs + self._cluster_codes = set() self._enum = Enum(name=attrs['name'], base_type=attrs['type'], entries=[]) @@ -260,10 +263,7 @@ def GetNextProcessor(self, name, attrs): )) return BaseHandler(self.context, handled=HandledDepth.SINGLE_TAG) elif name.lower() == 'cluster': - if self._cluster_code is not None: - raise Exception( - 'Multiple cluster codes for enum %s' % self._enum.name) - self._cluster_code = ParseInt(attrs['code']) + self._cluster_codes.add(ParseInt(attrs['code'])) return BaseHandler(self.context, handled=HandledDepth.SINGLE_TAG) else: return BaseHandler(self.context) @@ -273,18 +273,18 @@ def FinalizeProcessing(self, idl: Idl): # - inside a cluster if a code exists # - inside top level if a code does not exist - if self._cluster_code is None: + if not self._cluster_codes: idl.enums.append(self._enum) else: - found = False + found = set() for c in idl.clusters: - if c.code == self._cluster_code: + if c.code in self._cluster_codes: c.enums.append(self._enum) - found = True + found.add(c.code) - if not found: - LOGGER.error('Enum %s could not find its cluster (code %d/0x%X)' % - (self._enum.name, self._cluster_code, self._cluster_code)) + if found != self._cluster_codes: + LOGGER.error('Enum %s could not find its clusters (codes: %r)' % + (self._enum.name, self._cluster_codes - found)) def EndProcessing(self): self.context.AddIdlPostProcessor(self)