11#
2- # Copyright (c) 2023 Project CHIP Authors
2+ # Copyright (c) 2025 Project CHIP Authors
33# All rights reserved.
44#
55# Licensed under the Apache License, Version 2.0 (the "License");
1818import functools
1919from collections import defaultdict
2020from dataclasses import dataclass , field
21- from typing import Any
21+ from typing import Any , Dict , List , Set , Tuple
2222
2323import chip .clusters as Clusters
2424from chip .clusters .Types import Nullable
@@ -29,11 +29,11 @@ class TagProblem:
2929 root : int
3030 missing_attribute : bool
3131 missing_feature : bool
32- duplicates : set [int ]
33- same_tag : set [int ] = field (default_factory = set )
32+ duplicates : Set [int ]
33+ same_tag : Set [int ] = field (default_factory = set )
3434
3535
36- def separate_endpoint_types (endpoint_dict : dict [int , Any ]) -> tuple [ list [int ], list [int ]]:
36+ def separate_endpoint_types (endpoint_dict : Dict [int , Any ]) -> Tuple [ List [int ], List [int ]]:
3737 """Returns a tuple containing the list of flat endpoints and a list of tree endpoints"""
3838 flat = []
3939 tree = []
@@ -52,13 +52,13 @@ def separate_endpoint_types(endpoint_dict: dict[int, Any]) -> tuple[list[int], l
5252 return (flat , tree )
5353
5454
55- def get_all_children (endpoint_id , endpoint_dict : dict [int , Any ]) -> set [int ]:
55+ def get_all_children (endpoint_id : int , endpoint_dict : Dict [int , Any ]) -> Set [int ]:
5656 """Returns all the children (include subchildren) of the given endpoint
5757 This assumes we've already checked that there are no cycles, so we can do the dumb things and just trace the tree
5858 """
59- children = set ()
59+ children : Set [ int ] = set ()
6060
61- def add_children (endpoint_id , children ) :
61+ def add_children (endpoint_id : int , children : Set [ int ]) -> None :
6262 immediate_children = endpoint_dict [endpoint_id ][Clusters .Descriptor ][Clusters .Descriptor .Attributes .PartsList ]
6363 if not immediate_children :
6464 return
@@ -70,15 +70,16 @@ def add_children(endpoint_id, children):
7070 return children
7171
7272
73- def find_tree_roots (tree_endpoints : list [int ], endpoint_dict : dict [int , Any ]) -> set [int ]:
73+ def find_tree_roots (tree_endpoints : List [int ], endpoint_dict : Dict [int , Any ]) -> Set [int ]:
7474 """Returns a set of all the endpoints in tree_endpoints that are roots for a tree (not include singletons)"""
7575 tree_roots = set ()
7676
77- def find_tree_root (current_id ) :
77+ def find_tree_root (current_id : int ) -> int :
7878 for endpoint_id , endpoint in endpoint_dict .items ():
7979 if endpoint_id not in tree_endpoints :
8080 continue
81- if current_id in endpoint [Clusters .Descriptor ][Clusters .Descriptor .Attributes .PartsList ]:
81+ parts_list = endpoint [Clusters .Descriptor ][Clusters .Descriptor .Attributes .PartsList ]
82+ if current_id in parts_list :
8283 # this is not the root, move up
8384 return find_tree_root (endpoint_id )
8485 return current_id
@@ -90,9 +91,9 @@ def find_tree_root(current_id):
9091 return tree_roots
9192
9293
93- def parts_list_cycles (tree_endpoints : list [int ], endpoint_dict : dict [int , Any ]) -> list [int ]:
94+ def parts_list_cycles (tree_endpoints : List [int ], endpoint_dict : Dict [int , Any ]) -> List [int ]:
9495 """Returns a list of all the endpoints in the tree_endpoints list that contain cycles"""
95- def parts_list_cycle_detect (visited : set , current_id : int ) -> bool :
96+ def parts_list_cycle_detect (visited : Set [ int ] , current_id : int ) -> bool :
9697 if current_id in visited :
9798 return True
9899 visited .add (current_id )
@@ -105,28 +106,28 @@ def parts_list_cycle_detect(visited: set, current_id: int) -> bool:
105106 cycles = []
106107 # This is quick enough that we can do all the endpoints without searching for the roots
107108 for endpoint_id in tree_endpoints :
108- visited = set ()
109+ visited : Set [ int ] = set ()
109110 if parts_list_cycle_detect (visited , endpoint_id ):
110111 cycles .append (endpoint_id )
111112 return cycles
112113
113114
114- def create_device_type_lists (roots : list [int ], endpoint_dict : dict [int , Any ]) -> dict [int , dict [int , set [int ]]]:
115+ def create_device_type_lists (roots : List [int ], endpoint_dict : Dict [int , Any ]) -> Dict [int , Dict [int , Set [int ]]]:
115116 """Returns a list of endpoints per device type for each root in the list"""
116- device_types = {}
117+ device_types : Dict [ int , Dict [ int , Set [ int ]]] = {}
117118 for root in roots :
118- tree_device_types = defaultdict (set )
119+ tree_device_types : Dict [ int , Set [ int ]] = defaultdict (set )
119120 eps = get_all_children (root , endpoint_dict )
120121 eps .add (root )
121122 for ep in eps :
122123 for d in endpoint_dict [ep ][Clusters .Descriptor ][Clusters .Descriptor .Attributes .DeviceTypeList ]:
123124 tree_device_types [d .deviceType ].add (ep )
124- device_types [root ] = tree_device_types
125+ device_types [root ] = dict ( tree_device_types ) # Convert defaultdict to dict before storing
125126
126127 return device_types
127128
128129
129- def get_direct_children_of_root (endpoint_dict : dict [int , Any ]) -> set [int ]:
130+ def get_direct_children_of_root (endpoint_dict : Dict [int , Any ]) -> Set [int ]:
130131 root_children = set (endpoint_dict [0 ][Clusters .Descriptor ][Clusters .Descriptor .Attributes .PartsList ])
131132 direct_children = root_children
132133 for ep in root_children :
@@ -135,7 +136,7 @@ def get_direct_children_of_root(endpoint_dict: dict[int, Any]) -> set[int]:
135136 return direct_children
136137
137138
138- def create_device_type_list_for_root (direct_children , endpoint_dict : dict [int , Any ]) -> dict [int , set [int ]]:
139+ def create_device_type_list_for_root (direct_children : Set [ int ] , endpoint_dict : Dict [int , Any ]) -> Dict [int , Set [int ]]:
139140 device_types = defaultdict (set )
140141 for ep in direct_children :
141142 for d in endpoint_dict [ep ][Clusters .Descriptor ][Clusters .Descriptor .Attributes .DeviceTypeList ]:
@@ -147,19 +148,23 @@ def cmp_tag_list(a: Clusters.Descriptor.Structs.SemanticTagStruct, b: Clusters.D
147148 if type (a .mfgCode ) != type (b .mfgCode ):
148149 return - 1 if type (a .mfgCode ) is Nullable else 1
149150 if a .mfgCode != b .mfgCode :
150- return - 1 if a .mfgCode < b .mfgCode else 1
151+ # Adding type ignore for the comparison between potentially incompatible types
152+ result = - 1 if a .mfgCode < b .mfgCode else 1 # type: ignore
153+ return result
151154 if a .namespaceID != b .namespaceID :
152155 return - 1 if a .namespaceID < b .namespaceID else 1
153156 if a .tag != b .tag :
154157 return - 1 if a .tag < b .tag else 1
155158 if type (a .label ) != type (b .label ):
156159 return - 1 if type (a .label ) is Nullable or a .label is None else 1
157160 if a .label != b .label :
158- return - 1 if a .label < b .label else 1
161+ # Adding type ignore for the comparison between potentially incompatible types
162+ result = - 1 if a .label < b .label else 1 # type: ignore
163+ return result
159164 return 0
160165
161166
162- def find_tag_list_problems (roots : list [int ], device_types : dict [int , dict [int , set [int ]]], endpoint_dict : dict [int , Any ]) -> dict [int , TagProblem ]:
167+ def find_tag_list_problems (roots : List [int ], device_types : Dict [int , Dict [int , Set [int ]]], endpoint_dict : Dict [int , Any ]) -> Dict [int , TagProblem ]:
163168 """Checks for non-spec compliant tag lists"""
164169 tag_problems = {}
165170 for root in roots :
@@ -196,7 +201,7 @@ def find_tag_list_problems(roots: list[int], device_types: dict[int, dict[int, s
196201 return tag_problems
197202
198203
199- def flat_list_ok (flat_endpoint_id_to_check : int , endpoints_dict : dict [int , Any ]) -> bool :
204+ def flat_list_ok (flat_endpoint_id_to_check : int , endpoints_dict : Dict [int , Any ]) -> bool :
200205 '''Checks if the (flat) PartsList on the supplied endpoint contains all the sub-children of its parts.'''
201206 sub_children = set ()
202207 for child in endpoints_dict [flat_endpoint_id_to_check ][Clusters .Descriptor ][Clusters .Descriptor .Attributes .PartsList ]:
0 commit comments