Skip to content

Commit 5f6f3f1

Browse files
fixing type hints errors on python controller code (project-chip#34415)
* fixing mypy errors * restyled * add new files to BUILD.gn * mypy: fixing p256keypair.py * more mypy fixes * adding workaround to allow type hinting ctypes pointers * more mypy fixes * more mypy fixes * Restyled by autopep8 --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 6f84526 commit 5f6f3f1

File tree

13 files changed

+172
-169
lines changed

13 files changed

+172
-169
lines changed

src/controller/python/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ chip_python_wheel_action("chip-core") {
179179
"chip/commissioning/commissioning_flow_blocks.py",
180180
"chip/commissioning/pase.py",
181181
"chip/configuration/__init__.py",
182+
"chip/credentials/__init__.py",
182183
"chip/credentials/cert.py",
184+
"chip/crypto/__init__.py",
183185
"chip/crypto/fabric.py",
184186
"chip/crypto/p256keypair.py",
185187
"chip/discovery/__init__.py",

src/controller/python/chip/ChipDeviceCtrl.py

+45-47
Large diffs are not rendered by default.

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

+65-77
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@
2727
from ctypes import CFUNCTYPE, POINTER, c_size_t, c_uint8, c_uint16, c_uint32, c_uint64, c_void_p, cast, py_object
2828
from dataclasses import dataclass, field
2929
from enum import Enum, unique
30-
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
30+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
3131

3232
import chip
3333
import chip.exceptions
3434
import chip.interaction_model
3535
import chip.tlv
36-
import construct
36+
import construct # type: ignore
3737
from chip.interaction_model import PyWriteAttributeData
3838
from chip.native import ErrorSDKPart, PyChipError
39-
from rich.pretty import pprint
39+
from rich.pretty import pprint # type: ignore
4040

4141
from .ClusterObjects import Cluster, ClusterAttributeDescriptor, ClusterEvent
4242

@@ -58,9 +58,9 @@ class EventPriority(Enum):
5858

5959
@dataclass(frozen=True)
6060
class AttributePath:
61-
EndpointId: int = None
62-
ClusterId: int = None
63-
AttributeId: int = None
61+
EndpointId: Optional[int] = None
62+
ClusterId: Optional[int] = None
63+
AttributeId: Optional[int] = None
6464

6565
@staticmethod
6666
def from_cluster(EndpointId: int, Cluster: Cluster) -> AttributePath:
@@ -80,12 +80,12 @@ def __str__(self) -> str:
8080

8181
@dataclass(frozen=True)
8282
class DataVersionFilter:
83-
EndpointId: int = None
84-
ClusterId: int = None
85-
DataVersion: int = None
83+
EndpointId: Optional[int] = None
84+
ClusterId: Optional[int] = None
85+
DataVersion: Optional[int] = None
8686

8787
@staticmethod
88-
def from_cluster(EndpointId: int, Cluster: Cluster, DataVersion: int = None) -> AttributePath:
88+
def from_cluster(EndpointId: int, Cluster: Cluster, DataVersion: int) -> DataVersionFilter:
8989
if Cluster is None:
9090
raise ValueError("Cluster cannot be None")
9191
return DataVersionFilter(EndpointId=EndpointId, ClusterId=Cluster.id, DataVersion=DataVersion)
@@ -99,70 +99,67 @@ class TypedAttributePath:
9999
''' Encapsulates an attribute path that has strongly typed references to cluster and attribute
100100
cluster object types. These types serve as keys into the attribute cache.
101101
'''
102-
ClusterType: Cluster = None
103-
AttributeType: ClusterAttributeDescriptor = None
104-
AttributeName: str = None
105-
Path: AttributePath = None
106-
107-
def __init__(self, ClusterType: Cluster = None, AttributeType: ClusterAttributeDescriptor = None,
108-
Path: AttributePath = None):
109-
''' Only one of either ClusterType and AttributeType OR Path may be provided.
110-
'''
111-
112-
#
113-
# First, let's populate ClusterType and AttributeType. If it's already provided,
114-
# we can continue onwards to deriving the label. Otherwise, we'll need to
115-
# walk the attribute index to find the right type information.
116-
#
117-
if (ClusterType is not None and AttributeType is not None):
118-
self.ClusterType = ClusterType
119-
self.AttributeType = AttributeType
120-
else:
121-
if (Path is None):
122-
raise ValueError("Path should have a valid value")
123-
102+
ClusterType: Optional[Cluster] = None
103+
AttributeType: Optional[ClusterAttributeDescriptor] = None
104+
AttributeName: Optional[str] = None
105+
Path: Optional[AttributePath] = None
106+
ClusterId: Optional[int] = None
107+
AttributeId: Optional[int] = None
108+
109+
def __post_init__(self):
110+
'''Only one of either ClusterType and AttributeType OR Path may be provided.'''
111+
112+
if (self.ClusterType is not None and self.AttributeType is not None) and self.Path is not None:
113+
raise ValueError("Only one of either ClusterType and AttributeType OR Path may be provided.")
114+
if (self.ClusterType is None or self.AttributeType is None) and self.Path is None:
115+
raise ValueError("Either ClusterType and AttributeType OR Path must be provided.")
116+
117+
# if ClusterType and AttributeType were provided we can continue onwards to deriving the label.
118+
# Otherwise, we'll need to walk the attribute index to find the right type information.
119+
120+
# If Path is provided, derive ClusterType and AttributeType from it
121+
if self.Path is not None:
124122
for cluster, attribute in _AttributeIndex:
125123
attributeType = _AttributeIndex[(cluster, attribute)][0]
126124
clusterType = _AttributeIndex[(cluster, attribute)][1]
127125

128-
if (clusterType.id == Path.ClusterId and attributeType.attribute_id == Path.AttributeId):
126+
if clusterType.id == self.Path.ClusterId and attributeType.attribute_id == self.Path.AttributeId:
129127
self.ClusterType = clusterType
130128
self.AttributeType = attributeType
131129
break
132130

133-
if (self.ClusterType is None or self.AttributeType is None):
134-
raise KeyError(f"No Schema found for Attribute {Path}")
131+
if self.ClusterType is None or self.AttributeType is None:
132+
raise KeyError(f"No Schema found for Attribute {self.Path}")
135133

136134
# Next, let's figure out the label.
137135
for c_field in self.ClusterType.descriptor.Fields:
138-
if (c_field.Tag != self.AttributeType.attribute_id):
136+
if c_field.Tag != self.AttributeType.attribute_id:
139137
continue
140138

141139
self.AttributeName = c_field.Label
142140

143-
if (self.AttributeName is None):
144-
raise KeyError(f"Unable to resolve name for Attribute {Path}")
141+
if self.AttributeName is None:
142+
raise KeyError(f"Unable to resolve name for Attribute {self.Path}")
145143

146-
self.Path = Path
147144
self.ClusterId = self.ClusterType.id
148145
self.AttributeId = self.AttributeType.attribute_id
149146

150147

151148
@dataclass(frozen=True)
152149
class EventPath:
153-
EndpointId: int = None
154-
ClusterId: int = None
155-
EventId: int = None
156-
Urgent: int = None
150+
EndpointId: Optional[int] = None
151+
ClusterId: Optional[int] = None
152+
EventId: Optional[int] = None
153+
Urgent: Optional[int] = None
157154

158155
@staticmethod
159-
def from_cluster(EndpointId: int, Cluster: Cluster, EventId: int = None, Urgent: int = None) -> "EventPath":
156+
def from_cluster(EndpointId: int, Cluster: Cluster, EventId: Optional[int] = None, Urgent: Optional[int] = None) -> "EventPath":
160157
if Cluster is None:
161158
raise ValueError("Cluster cannot be None")
162159
return EventPath(EndpointId=EndpointId, ClusterId=Cluster.id, EventId=EventId, Urgent=Urgent)
163160

164161
@staticmethod
165-
def from_event(EndpointId: int, Event: ClusterEvent, Urgent: int = None) -> "EventPath":
162+
def from_event(EndpointId: int, Event: ClusterEvent, Urgent: Optional[int] = None) -> "EventPath":
166163
if Event is None:
167164
raise ValueError("Event cannot be None")
168165
return EventPath(EndpointId=EndpointId, ClusterId=Event.cluster_id, EventId=Event.event_id, Urgent=Urgent)
@@ -173,23 +170,13 @@ def __str__(self) -> str:
173170

174171
@dataclass
175172
class EventHeader:
176-
EndpointId: int = None
177-
ClusterId: int = None
178-
EventId: int = None
179-
EventNumber: int = None
180-
Priority: EventPriority = None
181-
Timestamp: int = None
182-
TimestampType: EventTimestampType = None
183-
184-
def __init__(self, EndpointId: int = None, ClusterId: int = None,
185-
EventId: int = None, EventNumber=None, Priority=None, Timestamp=None, TimestampType=None):
186-
self.EndpointId = EndpointId
187-
self.ClusterId = ClusterId
188-
self.EventId = EventId
189-
self.EventNumber = EventNumber
190-
self.Priority = Priority
191-
self.Timestamp = Timestamp
192-
self.TimestampType = TimestampType
173+
EndpointId: Optional[int] = None
174+
ClusterId: Optional[int] = None
175+
EventId: Optional[int] = None
176+
EventNumber: Optional[int] = None
177+
Priority: Optional[EventPriority] = None
178+
Timestamp: Optional[int] = None
179+
TimestampType: Optional[EventTimestampType] = None
193180

194181
def __str__(self) -> str:
195182
return (f"{self.EndpointId}/{self.ClusterId}/{self.EventId}/"
@@ -247,7 +234,7 @@ class ValueDecodeFailure:
247234
'''
248235

249236
TLVValue: Any = None
250-
Reason: Exception = None
237+
Reason: Optional[Exception] = None
251238

252239

253240
@dataclass
@@ -431,15 +418,16 @@ def handle_attribute_view(endpointId, clusterId, attributeId, attributeType):
431418

432419
class SubscriptionTransaction:
433420
def __init__(self, transaction: AsyncReadTransaction, subscriptionId, devCtrl):
434-
self._onResubscriptionAttemptedCb = DefaultResubscriptionAttemptedCallback
435-
self._onAttributeChangeCb = DefaultAttributeChangeCallback
436-
self._onEventChangeCb = DefaultEventChangeCallback
437-
self._onErrorCb = DefaultErrorCallback
421+
self._onResubscriptionAttemptedCb: Callable[[SubscriptionTransaction,
422+
int, int], None] = DefaultResubscriptionAttemptedCallback
423+
self._onAttributeChangeCb: Callable[[TypedAttributePath, SubscriptionTransaction], None] = DefaultAttributeChangeCallback
424+
self._onEventChangeCb: Callable[[EventReadResult, SubscriptionTransaction], None] = DefaultEventChangeCallback
425+
self._onErrorCb: Callable[[int, SubscriptionTransaction], None] = DefaultErrorCallback
438426
self._readTransaction = transaction
439427
self._subscriptionId = subscriptionId
440428
self._devCtrl = devCtrl
441429
self._isDone = False
442-
self._onResubscriptionSucceededCb = None
430+
self._onResubscriptionSucceededCb: Optional[Callable[[SubscriptionTransaction], None]] = None
443431
self._onResubscriptionSucceededCb_isAsync = False
444432
self._onResubscriptionAttemptedCb_isAsync = False
445433

@@ -647,10 +635,10 @@ def __init__(self, future: Future, eventLoop, devCtrl, returnClusterObject: bool
647635
self._event_loop = eventLoop
648636
self._future = future
649637
self._subscription_handler = None
650-
self._events = []
638+
self._events: List[EventReadResult] = []
651639
self._devCtrl = devCtrl
652640
self._cache = AttributeCache(returnClusterObject=returnClusterObject)
653-
self._changedPathSet = set()
641+
self._changedPathSet: Set[AttributePath] = set()
654642
self._pReadClient = None
655643
self._pReadCallback = None
656644
self._resultError: Optional[PyChipError] = None
@@ -809,7 +797,7 @@ class AsyncWriteTransaction:
809797
def __init__(self, future: Future, eventLoop):
810798
self._event_loop = eventLoop
811799
self._future = future
812-
self._resultData = []
800+
self._resultData: List[AttributeWriteResult] = []
813801
self._resultError: Optional[PyChipError] = None
814802

815803
def handleResponse(self, path: AttributePath, status: int):
@@ -1014,9 +1002,9 @@ def WriteGroupAttributes(groupId: int, devCtrl: c_void_p, attributes: List[Attri
10141002

10151003

10161004
def Read(future: Future, eventLoop, device, devCtrl,
1017-
attributes: List[AttributePath] = None, dataVersionFilters: List[DataVersionFilter] = None,
1018-
events: List[EventPath] = None, eventNumberFilter: Optional[int] = None, returnClusterObject: bool = True,
1019-
subscriptionParameters: SubscriptionParameters = None,
1005+
attributes: Optional[List[AttributePath]] = None, dataVersionFilters: Optional[List[DataVersionFilter]] = None,
1006+
events: Optional[List[EventPath]] = None, eventNumberFilter: Optional[int] = None, returnClusterObject: bool = True,
1007+
subscriptionParameters: Optional[SubscriptionParameters] = None,
10201008
fabricFiltered: bool = True, keepSubscriptions: bool = False, autoResubscribe: bool = True) -> PyChipError:
10211009
if (not attributes) and dataVersionFilters:
10221010
raise ValueError(
@@ -1132,9 +1120,9 @@ def Read(future: Future, eventLoop, device, devCtrl,
11321120

11331121

11341122
def ReadAttributes(future: Future, eventLoop, device, devCtrl,
1135-
attributes: List[AttributePath], dataVersionFilters: List[DataVersionFilter] = None,
1123+
attributes: List[AttributePath], dataVersionFilters: Optional[List[DataVersionFilter]] = None,
11361124
returnClusterObject: bool = True,
1137-
subscriptionParameters: SubscriptionParameters = None, fabricFiltered: bool = True) -> int:
1125+
subscriptionParameters: Optional[SubscriptionParameters] = None, fabricFiltered: bool = True) -> int:
11381126
return Read(future=future, eventLoop=eventLoop, device=device,
11391127
devCtrl=devCtrl, attributes=attributes, dataVersionFilters=dataVersionFilters,
11401128
events=None, returnClusterObject=returnClusterObject,
@@ -1143,7 +1131,7 @@ def ReadAttributes(future: Future, eventLoop, device, devCtrl,
11431131

11441132
def ReadEvents(future: Future, eventLoop, device, devCtrl,
11451133
events: List[EventPath], eventNumberFilter=None, returnClusterObject: bool = True,
1146-
subscriptionParameters: SubscriptionParameters = None, fabricFiltered: bool = True) -> int:
1134+
subscriptionParameters: Optional[SubscriptionParameters] = None, fabricFiltered: bool = True) -> int:
11471135
return Read(future=future, eventLoop=eventLoop, device=device, devCtrl=devCtrl, attributes=None,
11481136
dataVersionFilters=None, events=events, eventNumberFilter=eventNumberFilter,
11491137
returnClusterObject=returnClusterObject,

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

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from chip import ChipUtility, tlv
2424
from chip.clusters.Types import Nullable, NullValue
25-
from dacite import from_dict
25+
from dacite import from_dict # type: ignore
2626

2727

2828
def GetUnionUnderlyingType(typeToCheck, matchingType=None):
@@ -52,8 +52,8 @@ def GetUnionUnderlyingType(typeToCheck, matchingType=None):
5252
@dataclass
5353
class ClusterObjectFieldDescriptor:
5454
Label: str = ''
55-
Tag: int = None
56-
Type: type = None
55+
Tag: typing.Optional[int] = None
56+
Type: type = type(None)
5757

5858
def _PutSingleElementToTLV(self, tag, val, elementType, writer: tlv.TLVWriter, debugPath: str = '?'):
5959
if issubclass(elementType, ClusterObject):
@@ -113,13 +113,13 @@ def PutFieldToTLV(self, tag, val, writer: tlv.TLVWriter, debugPath: str = '?'):
113113
class ClusterObjectDescriptor:
114114
Fields: List[ClusterObjectFieldDescriptor]
115115

116-
def GetFieldByTag(self, tag: int) -> ClusterObjectFieldDescriptor:
116+
def GetFieldByTag(self, tag: int) -> typing.Optional[ClusterObjectFieldDescriptor]:
117117
for _field in self.Fields:
118118
if _field.Tag == tag:
119119
return _field
120120
return None
121121

122-
def GetFieldByLabel(self, label: str) -> ClusterObjectFieldDescriptor:
122+
def GetFieldByLabel(self, label: str) -> typing.Optional[ClusterObjectFieldDescriptor]:
123123
for _field in self.Fields:
124124
if _field.Label == label:
125125
return _field
@@ -140,7 +140,7 @@ def _ConvertNonArray(self, debugPath: str, elementType, value: Any) -> Any:
140140
return elementType.descriptor.TagDictToLabelDict(debugPath, value)
141141

142142
def TagDictToLabelDict(self, debugPath: str, tlvData: Dict[int, Any]) -> Dict[str, Any]:
143-
ret = {}
143+
ret: typing.Dict[Any, Any] = {}
144144
for tag, value in tlvData.items():
145145
descriptor = self.GetFieldByTag(tag)
146146
if not descriptor:
@@ -156,7 +156,7 @@ def TagDictToLabelDict(self, debugPath: str, tlvData: Dict[int, Any]) -> Dict[st
156156
realType = GetUnionUnderlyingType(descriptor.Type)
157157
if (realType is None):
158158
raise ValueError(
159-
f"Field {debugPath}.{self.Label} has no valid underlying data model type")
159+
f"Field {debugPath}.{descriptor.Label} has no valid underlying data model type")
160160

161161
valueType = realType
162162
else:
@@ -175,7 +175,7 @@ def TagDictToLabelDict(self, debugPath: str, tlvData: Dict[int, Any]) -> Dict[st
175175

176176
def TLVToDict(self, tlvBuf: bytes) -> Dict[str, Any]:
177177
tlvData = tlv.TLVReader(tlvBuf).get().get('Any', {})
178-
return self.TagDictToLabelDict([], tlvData)
178+
return self.TagDictToLabelDict('', tlvData)
179179

180180
def DictToTLVWithWriter(self, debugPath: str, tag, data: Mapping, writer: tlv.TLVWriter):
181181
writer.startStructure(tag)
@@ -209,11 +209,11 @@ def descriptor(cls):
209209

210210
# The below dictionaries will be filled dynamically
211211
# and are used for quick lookup/mapping from cluster/attribute id to the correct class
212-
ALL_CLUSTERS = {}
213-
ALL_ATTRIBUTES = {}
212+
ALL_CLUSTERS: typing.Dict = {}
213+
ALL_ATTRIBUTES: typing.Dict = {}
214214
# These need to be separate because there can be overlap in command ids for commands and responses.
215-
ALL_ACCEPTED_COMMANDS = {}
216-
ALL_GENERATED_COMMANDS = {}
215+
ALL_ACCEPTED_COMMANDS: typing.Dict = {}
216+
ALL_GENERATED_COMMANDS: typing.Dict = {}
217217

218218

219219
class ClusterCommand(ClusterObject):

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from threading import Lock
1919

20-
from aenum import IntEnum, extend_enum
20+
from aenum import IntEnum, extend_enum # type: ignore
2121

2222
# Flag on whether we should map unknown enum values to kUnknownEnumValue.
2323
_map_missing_enum_to_unknown_enum_value = True

src/controller/python/chip/credentials/__init__.py

Whitespace-only changes.

src/controller/python/chip/crypto/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)