Skip to content

Commit e56a0ce

Browse files
authored
Merge pull request #18 from tekktrik/doc/add-typing
Add type annotations, updates to documentation
2 parents 7d5c23e + c74470a commit e56a0ce

File tree

1 file changed

+73
-39
lines changed

1 file changed

+73
-39
lines changed

adafruit_aws_iot.py

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
import json
2727
from adafruit_minimqtt.adafruit_minimqtt import MMQTTException
2828

29+
try:
30+
from typing import Optional, Type, Union
31+
from types import TracebackType
32+
from adafruit_minimqtt.adafruit_minimqtt import MQTT
33+
except ImportError:
34+
pass
35+
2936
__version__ = "0.0.0-auto.0"
3037
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_AWS_IOT.git"
3138

@@ -40,13 +47,13 @@ class AWS_IOT_ERROR(Exception):
4047
class MQTT_CLIENT:
4148
"""Client for interacting with Amazon AWS IoT MQTT API.
4249
43-
:param MiniMQTT mmqttclient: Pre-configured MiniMQTT Client object.
50+
:param ~MQTT.MQTT mmqttclient: Pre-configured MiniMQTT Client object.
4451
:param int keep_alive: Optional Keep-alive timer interval, in seconds.
4552
Provided interval must be 30 <= keep_alive <= 1200.
4653
4754
"""
4855

49-
def __init__(self, mmqttclient, keep_alive=30):
56+
def __init__(self, mmqttclient: MQTT, keep_alive: int = 30) -> None:
5057
if "MQTT" in str(type(mmqttclient)):
5158
self.client = mmqttclient
5259
else:
@@ -88,18 +95,23 @@ def __init__(self, mmqttclient, keep_alive=30):
8895
self.client.on_unsubscribe = self._on_unsubscribe_mqtt
8996
self.connected_to_aws = False
9097

91-
def __enter__(self):
98+
def __enter__(self) -> "MQTT_CLIENT":
9299
return self
93100

94-
def __exit__(self, exception_type, exception_value, traceback):
101+
def __exit__(
102+
self,
103+
exception_type: Optional[Type[type]],
104+
exception_value: Optional[BaseException],
105+
traceback: Optional[TracebackType],
106+
) -> None:
95107
self.disconnect()
96108

97109
@property
98-
def is_connected(self):
110+
def is_connected(self) -> bool:
99111
"""Returns if MQTT_CLIENT is connected to AWS IoT MQTT Broker"""
100112
return self.connected_to_aws
101113

102-
def disconnect(self):
114+
def disconnect(self) -> None:
103115
"""Disconnects from Amazon AWS IoT MQTT Broker and de-initializes the MiniMQTT Client."""
104116
try:
105117
self.client.disconnect()
@@ -114,15 +126,16 @@ def disconnect(self):
114126
self.on_unsubscribe = None
115127
self.client.deinit()
116128

117-
def reconnect(self):
129+
def reconnect(self) -> None:
118130
"""Reconnects to the AWS IoT MQTT Broker"""
119131
try:
120132
self.client.reconnect()
121133
except MMQTTException as error:
122134
raise AWS_IOT_ERROR("Error re-connecting to AWS IoT:", error) from error
123135

124-
def connect(self, clean_session=True):
136+
def connect(self, clean_session: bool = True) -> None:
125137
"""Connects to Amazon AWS IoT MQTT Broker with Client ID.
138+
126139
:param bool clean_session: Establishes a clean session with AWS broker.
127140
128141
"""
@@ -134,9 +147,12 @@ def connect(self, clean_session=True):
134147

135148
# MiniMQTT Callback Handlers
136149
# pylint: disable=not-callable, unused-argument
137-
def _on_connect_mqtt(self, client, userdata, flag, ret_code):
150+
def _on_connect_mqtt(
151+
self, client: MQTT, userdata: str, flag: int, ret_code: int
152+
) -> None:
138153
"""Runs when code calls on_connect.
139-
:param MiniMQTT client: MiniMQTT client object.
154+
155+
:param ~MQTT.MQTT client: MiniMQTT client object.
140156
:param str user_data: User data from broker
141157
:param int flag: QoS flag from broker.
142158
:param int ret_code: Return code from broker.
@@ -148,9 +164,12 @@ def _on_connect_mqtt(self, client, userdata, flag, ret_code):
148164
self.on_connect(self, userdata, flag, ret_code)
149165

150166
# pylint: disable=not-callable, unused-argument
151-
def _on_disconnect_mqtt(self, client, userdata, flag, ret_code):
167+
def _on_disconnect_mqtt(
168+
self, client: MQTT, userdata: str, flag: int, ret_code: int
169+
) -> None:
152170
"""Runs when code calls on_disconnect.
153-
:param MiniMQTT client: MiniMQTT client object.
171+
172+
:param ~MQTT.MQTT client: MiniMQTT client object.
154173
:param str user_data: User data from broker
155174
:param int flag: QoS flag from broker.
156175
:param int ret_code: Return code from broker.
@@ -162,9 +181,10 @@ def _on_disconnect_mqtt(self, client, userdata, flag, ret_code):
162181
self.on_connect(self, userdata, flag, ret_code)
163182

164183
# pylint: disable=not-callable
165-
def _on_message_mqtt(self, client, topic, payload):
184+
def _on_message_mqtt(self, client: MQTT, topic: str, payload: str) -> None:
166185
"""Runs when the client calls on_message.
167-
:param MiniMQTT client: MiniMQTT client object.
186+
187+
:param ~MQTT.MQTT client: MiniMQTT client object.
168188
:param str topic: MQTT broker topic.
169189
:param str payload: Payload returned by MQTT broker topic
170190
@@ -173,26 +193,36 @@ def _on_message_mqtt(self, client, topic, payload):
173193
self.on_message(self, topic, payload)
174194

175195
# pylint: disable=not-callable
176-
def _on_subscribe_mqtt(self, client, user_data, topic, qos):
196+
def _on_subscribe_mqtt(
197+
self, client: MQTT, user_data: str, topic: int, qos: int
198+
) -> None:
177199
"""Runs when the client calls on_subscribe.
178200
179-
:param MiniMQTT client: MiniMQTT client object.
201+
:param ~MQTT.MQTT client: MiniMQTT client object.
180202
:param str user_data: User data from broker
181203
:param str topic: Desired MQTT topic.
182-
param int qos: Quality of service level for topic, from broker.
204+
:param int qos: Quality of service level for topic, from broker.
183205
184206
"""
185207
if self.on_subscribe is not None:
186208
self.on_subscribe(self, user_data, topic, qos)
187209

188210
# pylint: disable=not-callable
189-
def _on_unsubscribe_mqtt(self, client, user_data, topic, pid):
190-
"""Runs when the client calls on_unsubscribe."""
211+
def _on_unsubscribe_mqtt(
212+
self, client: MQTT, user_data: str, topic: str, pid: int
213+
) -> None:
214+
"""Runs when the client calls on_unsubscribe.
215+
216+
:param ~MQTT.MQTT client: MiniMQTT client object.
217+
:param str user_data: User data from broker
218+
:param str topic: Desired MQTT topic.
219+
:param int pid: Process ID.
220+
"""
191221
if self.on_unsubscribe is not None:
192222
self.on_unsubscribe(self, user_data, topic, pid)
193223

194224
# MiniMQTT Network Control Flow
195-
def loop(self):
225+
def loop(self) -> None:
196226
"""Starts a synchronous message loop which maintains connection with AWS IoT.
197227
Must be called within the keep_alive timeout specified to init.
198228
This method does not handle network connection/disconnection.
@@ -207,28 +237,28 @@ def loop(self):
207237
if self.connected_to_aws:
208238
self.client.loop()
209239

210-
def loop_forever(self):
240+
def loop_forever(self) -> None:
211241
"""Begins a blocking, asynchronous message loop.
212242
This method handles network connection/disconnection.
213-
214243
"""
215244
if self.connected_to_aws:
216245
self.client.loop_forever()
217246

218247
@staticmethod
219-
def validate_topic(topic):
248+
def validate_topic(topic: str) -> None:
220249
"""Validates if user-provided pub/sub topics adhere to AWS Service Limits.
221250
https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html
222-
:param str topic: Desired topic to validate
223251
252+
:param str topic: Desired topic to validate
224253
"""
225254
assert hasattr(topic, "split"), "Topic must be a string"
226255
assert len(topic) < 256, "Topic must be less than 256 bytes!"
227256
assert len(topic.split("/")) <= 9, "Topics are limited to 7 forward slashes."
228257

229258
# MiniMQTT Pub/Sub Methods, for usage with AWS IoT
230-
def subscribe(self, topic, qos=1):
259+
def subscribe(self, topic: str, qos: int = 1) -> None:
231260
"""Subscribes to an AWS IoT Topic.
261+
232262
:param str topic: MQTT topic to subscribe to.
233263
:param int qos: Desired topic subscription's quality-of-service.
234264
@@ -237,14 +267,16 @@ def subscribe(self, topic, qos=1):
237267
self.validate_topic(topic)
238268
self.client.subscribe(topic, qos)
239269

240-
def publish(self, topic, payload, qos=1):
270+
def publish(
271+
self, topic: str, payload: Union[str, float, bytes], qos: int = 1
272+
) -> None:
241273
"""Publishes to a AWS IoT Topic.
274+
242275
:param str topic: MQTT topic to publish to.
243-
:param str payload: Data to publish to topic.
244-
:param int payload: Data to publish to topic.
245-
:param float payload: Data to publish to topic.
246-
:param json payload: JSON-formatted data to publish to topic.
247-
:param int qos: Quality of service level for publishing.
276+
:param payload: Data to publish to topic. Must be able to be converted
277+
to a string using ``str()``
278+
:type payload: str|float|bytes
279+
:param int qos: Quality of service level for publishing
248280
249281
"""
250282
assert qos < 2, "AWS IoT does not support publishing with QoS 2."
@@ -255,35 +287,37 @@ def publish(self, topic, payload, qos=1):
255287

256288
# AWS IoT Device Shadow Service
257289

258-
def shadow_get_subscribe(self, qos=1):
290+
def shadow_get_subscribe(self, qos: int = 1) -> None:
259291
"""Subscribes to device's shadow get response.
260-
:param int qos: Optional quality of service level.
261292
293+
:param int qos: Optional quality of service level.
262294
"""
263295
self.client.subscribe(self.shadow_topic + "/get/#", qos)
264296

265-
def shadow_subscribe(self, qos=1):
297+
def shadow_subscribe(self, qos: int = 1) -> None:
266298
"""Subscribes to all notifications on the device's shadow update topic.
267-
:param int qos: Optional quality of service level.
268299
300+
:param int qos: Optional quality of service level.
269301
"""
270302
self.client.subscribe(self.shadow_topic + "/update/#", qos)
271303

272-
def shadow_update(self, document):
304+
def shadow_update(self, document: str):
273305
"""Publishes a request state document to update the device's shadow.
274-
:param json state_document: JSON-formatted state document.
275306
307+
:param str state_document: JSON-formatted state document string.
276308
"""
277309
self.client.publish(self.shadow_topic + "/update", document)
278310

279-
def shadow_get(self):
311+
def shadow_get(self) -> None:
280312
"""Publishes an empty message to shadow get topic to get the device's shadow."""
313+
281314
self.client.publish(
282315
self.shadow_topic + "/get", json.dumps({"message": "ignore"})
283316
)
284317

285-
def shadow_delete(self):
318+
def shadow_delete(self) -> None:
286319
"""Publishes an empty message to the shadow delete topic to delete a device's shadow"""
320+
287321
self.client.publish(
288322
self.shadow_topic + "/delete", json.dumps({"message": "delete"})
289323
)

0 commit comments

Comments
 (0)