Skip to content

Commit 055c5e2

Browse files
committed
[Python] Make AttributePath more pythonic
Use dataclass default initializer to initialize AttributePath. Use static method to initialize from Cluster or Attribute. Also hash the integer fields directly, this is more efficient than formatting a string first.
1 parent 174f2a0 commit 055c5e2

File tree

3 files changed

+20
-34
lines changed

3 files changed

+20
-34
lines changed

src/controller/python/chip/ChipDeviceCtrl.py

+7-14
Original file line numberDiff line numberDiff line change
@@ -1170,33 +1170,26 @@ def _parseAttributePathTuple(self, pathTuple: typing.Union[
11701170
# Concrete path
11711171
typing.Tuple[int, typing.Type[ClusterObjects.ClusterAttributeDescriptor]]
11721172
]):
1173-
endpoint = None
1174-
cluster = None
1175-
attribute = None
1176-
11771173
if pathTuple == ('*') or pathTuple == ():
11781174
# Wildcard
1179-
pass
1175+
return ClusterAttribute.AttributePath()
11801176
elif not isinstance(pathTuple, tuple):
11811177
if isinstance(pathTuple, int):
1182-
endpoint = pathTuple
1178+
return ClusterAttribute.AttributePath(EndpointId=pathTuple)
11831179
elif issubclass(pathTuple, ClusterObjects.Cluster):
1184-
cluster = pathTuple
1180+
return ClusterAttribute.AttributePath.from_cluster(EndpointId=None, Cluster=pathTuple)
11851181
elif issubclass(pathTuple, ClusterObjects.ClusterAttributeDescriptor):
1186-
attribute = pathTuple
1182+
return ClusterAttribute.AttributePath.from_attribute(EndpointId=None, Attribute=pathTuple)
11871183
else:
11881184
raise ValueError("Unsupported Attribute Path")
11891185
else:
11901186
# endpoint + (cluster) attribute / endpoint + cluster
1191-
endpoint = pathTuple[0]
11921187
if issubclass(pathTuple[1], ClusterObjects.Cluster):
1193-
cluster = pathTuple[1]
1188+
return ClusterAttribute.AttributePath.from_cluster(EndpointId=pathTuple[0], Cluster=pathTuple[1])
11941189
elif issubclass(pathTuple[1], ClusterAttribute.ClusterAttributeDescriptor):
1195-
attribute = pathTuple[1]
1190+
return ClusterAttribute.AttributePath.from_attribute(EndpointId=pathTuple[0], Attribute=pathTuple[1])
11961191
else:
11971192
raise ValueError("Unsupported Attribute Path")
1198-
return ClusterAttribute.AttributePath(
1199-
EndpointId=endpoint, Cluster=cluster, Attribute=attribute)
12001193

12011194
def _parseDataVersionFilterTuple(self, pathTuple: typing.List[typing.Tuple[int, typing.Type[ClusterObjects.Cluster], int]]):
12021195
endpoint = None
@@ -1530,7 +1523,7 @@ def ZCLReadAttribute(self, cluster, attribute, nodeid, endpoint, groupid, blocki
15301523

15311524
result = asyncio.run(self.ReadAttribute(
15321525
nodeid, [(endpoint, attributeType)]))
1533-
path = ClusterAttribute.AttributePath(
1526+
path = ClusterAttribute.AttributePath.from_attribute(
15341527
EndpointId=endpoint, Attribute=attributeType)
15351528
return im.AttributeReadResult(path=im.AttributePath(nodeId=nodeid, endpointId=path.EndpointId, clusterId=path.ClusterId, attributeId=path.AttributeId),
15361529
status=0, value=result[endpoint][clusterType][attributeType], dataVersion=result[endpoint][clusterType][ClusterAttribute.DataVersion])

src/controller/python/chip/clusters/Attribute.py

+12-19
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,23 @@ class AttributePath:
6060
ClusterId: int = None
6161
AttributeId: int = None
6262

63-
def __init__(self, EndpointId: int = None, Cluster=None, Attribute=None, ClusterId=None, AttributeId=None):
64-
self.EndpointId = EndpointId
65-
if Cluster is not None:
66-
# Wildcard read for a specific cluster
67-
if (Attribute is not None) or (ClusterId is not None) or (AttributeId is not None):
68-
raise Warning(
69-
"Attribute, ClusterId and AttributeId is ignored when Cluster is specified")
70-
self.ClusterId = Cluster.id
71-
return
72-
if Attribute is not None:
73-
if (ClusterId is not None) or (AttributeId is not None):
74-
raise Warning(
75-
"ClusterId and AttributeId is ignored when Attribute is specified")
76-
self.ClusterId = Attribute.cluster_id
77-
self.AttributeId = Attribute.attribute_id
78-
return
79-
self.ClusterId = ClusterId
80-
self.AttributeId = AttributeId
63+
@staticmethod
64+
def from_cluster(EndpointId: int, Cluster: Cluster) -> AttributePath:
65+
if Cluster is None:
66+
raise ValueError("Cluster cannot be None")
67+
return AttributePath(EndpointId=EndpointId, ClusterId=Cluster.id)
68+
69+
@staticmethod
70+
def from_attribute(EndpointId: int, Attribute: ClusterAttributeDescriptor) -> AttributePath:
71+
if Attribute is None:
72+
raise ValueError("Attribute cannot be None")
73+
return AttributePath(EndpointId=EndpointId, ClusterId=Attribute.cluster_id, AttributeId=Attribute.attribute_id)
8174

8275
def __str__(self) -> str:
8376
return f"{self.EndpointId}/{self.ClusterId}/{self.AttributeId}"
8477

8578
def __hash__(self):
86-
return str(self).__hash__()
79+
return hash((self.EndpointId, self.ClusterId, self.AttributeId))
8780

8881

8982
@dataclass

src/controller/python/test/test_scripts/cluster_objects.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ async def TestWriteRequest(cls, devCtrl):
164164
]
165165
)
166166
expectedRes = [
167-
AttributeStatus(Path=AttributePath(
167+
AttributeStatus(Path=AttributePath.from_attribute(
168168
EndpointId=1,
169169
Attribute=Clusters.UnitTesting.Attributes.ListLongOctetString), Status=chip.interaction_model.Status.Success),
170170
]

0 commit comments

Comments
 (0)