Skip to content

Commit b55852b

Browse files
authored
[Python] Improve attribute cache code quality (project-chip#31074)
* Improve/fix exception handling in attribute update callbacks Commit 79cebcf ("[controller] Fix flake8 warnings (project-chip#25311)") changed the exceptions catched from a global catch to a specific catch for chip.exceptions.ChipStackException exceptions. However, in this two cases the error is just converted to a Python enum, there is no case where chip.exceptions.ChipStackException would be raised. Since those callbacks are called from the C++ SDK, to the best of my knowledge, the intention was that exception would not bubble up into SDK code. Handle the Python specific exceptions and make sure they get logged verbosley. * [Python] Simplify UpdateCachedData for better readability Extract cache type implementation in functions. Also make the code a bit more Pythonic. Note: This no longer initializes endpointCache in the Cluster-View. This shouldn't matter in practice as the dictionary wasn't used.
1 parent 00bdcd3 commit b55852b

File tree

1 file changed

+30
-52
lines changed

1 file changed

+30
-52
lines changed

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

+30-52
Original file line numberDiff line numberDiff line change
@@ -408,18 +408,30 @@ def UpdateCachedData(self, changedPathSet: set[AttributePath]):
408408
instead of a cluster object value, a ValueDecodeFailure shall be present.
409409
'''
410410

411-
tlvCache = self.attributeTLVCache
412-
attributeCache = self.attributeCache
411+
def handle_cluster_view(endpointId, clusterId, clusterType):
412+
try:
413+
decodedData = clusterType.FromDict(
414+
data=clusterType.descriptor.TagDictToLabelDict([], self.attributeTLVCache[endpointId][clusterId]))
415+
decodedData.SetDataVersion(self.versionList.get(endpointId, {}).get(clusterId))
416+
return decodedData
417+
except Exception as ex:
418+
return ValueDecodeFailure(self.attributeTLVCache[endpointId][clusterId], ex)
419+
420+
def handle_attribute_view(endpointId, clusterId, attributeId, attributeType):
421+
value = self.attributeTLVCache[endpointId][clusterId][attributeId]
422+
if isinstance(value, ValueDecodeFailure):
423+
return value
424+
try:
425+
return attributeType.FromTagDictOrRawValue(value)
426+
except Exception as ex:
427+
return ValueDecodeFailure(value, ex)
413428

414429
for attributePath in changedPathSet:
415-
endpointId = attributePath.EndpointId
416-
417-
if endpointId not in attributeCache:
418-
attributeCache[endpointId] = {}
430+
endpointId, clusterId, attributeId = attributePath.EndpointId, attributePath.ClusterId, attributePath.AttributeId
419431

420-
endpointCache = attributeCache[endpointId]
421-
422-
clusterId = attributePath.ClusterId
432+
if endpointId not in self.attributeCache:
433+
self.attributeCache[endpointId] = {}
434+
endpointCache = self.attributeCache[endpointId]
423435

424436
if clusterId not in _ClusterIndex:
425437
#
@@ -430,30 +442,13 @@ def UpdateCachedData(self, changedPathSet: set[AttributePath]):
430442

431443
clusterType = _ClusterIndex[clusterId]
432444

433-
if clusterType not in endpointCache:
434-
endpointCache[clusterType] = {}
435-
436-
clusterCache = endpointCache[clusterType]
437-
clusterDataVersion = self.versionList.get(
438-
endpointId, {}).get(clusterId, None)
439-
440445
if self.returnClusterObject:
441-
try:
442-
# Since the TLV data is already organized by attribute tags, we can trivially convert to a cluster object representation.
443-
endpointCache[clusterType] = clusterType.FromDict(
444-
data=clusterType.descriptor.TagDictToLabelDict([], tlvCache[endpointId][clusterId]))
445-
endpointCache[clusterType].SetDataVersion(
446-
clusterDataVersion)
447-
except Exception as ex:
448-
decodedValue = ValueDecodeFailure(
449-
tlvCache[endpointId][clusterId], ex)
450-
endpointCache[clusterType] = decodedValue
446+
endpointCache[clusterType] = handle_cluster_view(endpointId, clusterId, clusterType)
451447
else:
452-
clusterCache[DataVersion] = clusterDataVersion
453-
454-
attributeId = attributePath.AttributeId
455-
456-
value = tlvCache[endpointId][clusterId][attributeId]
448+
if clusterType not in endpointCache:
449+
endpointCache[clusterType] = {}
450+
clusterCache = endpointCache[clusterType]
451+
clusterCache[DataVersion] = self.versionList.get(endpointId, {}).get(clusterId)
457452

458453
if (clusterId, attributeId) not in _AttributeIndex:
459454
#
@@ -463,20 +458,7 @@ def UpdateCachedData(self, changedPathSet: set[AttributePath]):
463458
continue
464459

465460
attributeType = _AttributeIndex[(clusterId, attributeId)][0]
466-
467-
if attributeType not in clusterCache:
468-
clusterCache[attributeType] = {}
469-
470-
if isinstance(value, ValueDecodeFailure):
471-
clusterCache[attributeType] = value
472-
else:
473-
try:
474-
decodedValue = attributeType.FromTagDictOrRawValue(
475-
tlvCache[endpointId][clusterId][attributeId])
476-
except Exception as ex:
477-
decodedValue = ValueDecodeFailure(value, ex)
478-
479-
clusterCache[attributeType] = decodedValue
461+
clusterCache[attributeType] = handle_attribute_view(endpointId, clusterId, attributeId, attributeType)
480462

481463

482464
class SubscriptionTransaction:
@@ -692,11 +674,7 @@ def GetAllEventValues(self):
692674

693675
def handleAttributeData(self, path: AttributePathWithListIndex, dataVersion: int, status: int, data: bytes):
694676
try:
695-
imStatus = status
696-
try:
697-
imStatus = chip.interaction_model.Status(status)
698-
except chip.exceptions.ChipStackException:
699-
pass
677+
imStatus = chip.interaction_model.Status(status)
700678

701679
if (imStatus != chip.interaction_model.Status.Success):
702680
attributeValue = ValueDecodeFailure(
@@ -849,8 +827,8 @@ def handleResponse(self, path: AttributePath, status: int):
849827
try:
850828
imStatus = chip.interaction_model.Status(status)
851829
self._resultData.append(AttributeWriteResult(Path=path, Status=imStatus))
852-
except chip.exceptions.ChipStackException:
853-
self._resultData.append(AttributeWriteResult(Path=path, Status=status))
830+
except ValueError as ex:
831+
logging.exception(ex)
854832

855833
def handleError(self, chipError: PyChipError):
856834
self._resultError = chipError

0 commit comments

Comments
 (0)