diff --git a/scripts/py_matter_idl/BUILD.gn b/scripts/py_matter_idl/BUILD.gn index 37b17477aabfbc..01983d0a890724 100644 --- a/scripts/py_matter_idl/BUILD.gn +++ b/scripts/py_matter_idl/BUILD.gn @@ -64,6 +64,7 @@ pw_python_package("matter_idl") { tests = [ "matter_idl/test_backwards_compatibility.py", + "matter_idl/test_data_model_xml.py", "matter_idl/test_matter_idl_parser.py", "matter_idl/test_generators.py", "matter_idl/test_idl_generator.py", diff --git a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/derivation.py b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/derivation.py index 8102793ef20b12..79ddb29974b568 100644 --- a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/derivation.py +++ b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/derivation.py @@ -13,10 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # +import dataclasses import logging from typing import Iterable, Optional, Protocol, TypeVar -from matter_idl.matter_idl_types import Attribute, Bitmap, Cluster, Command, Enum, Event, Idl, Struct +from matter_idl.matter_idl_types import Attribute, AttributeQuality, Bitmap, Cluster, Command, Enum, Event, Idl, Struct from .context import Context, IdlPostProcessor from .parsing import NormalizeName @@ -81,6 +82,9 @@ def merge_event_into(e: Event, cluster: Cluster): def merge_attribute_into(a: Attribute, cluster: Cluster): + """Pushes an attribute from a base cluster into an already + parsed cluster. + """ existing: Optional[Attribute] = None for existing_a in cluster.attributes: if existing_a.definition.name == a.definition.name: @@ -90,13 +94,21 @@ def merge_attribute_into(a: Attribute, cluster: Cluster): if existing: # Merge examples: # UserLabelCluster::LabelList changes qualities (access, mandatory) - # - # TODO: add more examples and handle accordingly, sometimes just the - # conformance is changed - # - # To replace we could do: - # cluster.attributes.remove(existing) - # However then we lose any overrides + # ModeDishwasher: + # - changes the type of a list from sint32 to list[ModeOptionStruct] + # - Sets the field as read-only + + # Carry over data type and definitions, except quality and maturity + existing.definition = dataclasses.replace( + a.definition, + qualities=existing.definition.qualities, + api_maturity=existing.definition.api_maturity, + ) + + # Inherit attribute quality + if existing.qualities == AttributeQuality.NONE: + existing.qualities = a.qualities + return cluster.attributes.append(a) diff --git a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py index 6117f35e9f1ad2..06418f894ffcd6 100755 --- a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py +++ b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py @@ -214,15 +214,13 @@ def testClusterDerivation(self): ModeTagStruct modeTags[] = 2; } + readonly attribute ModeOptionStruct supportedModes[] = 0; readonly attribute attrib_id attributeList[] = 65531; readonly attribute event_id eventList[] = 65530; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; - - // baseline inserted after, so to pass the test add this at the end - readonly attribute ModeOptionStruct supportedModes[] = 0; } ''')