From 04d1a68d27e6904337fa19559babfe0b79ca6374 Mon Sep 17 00:00:00 2001 From: Mahe Iram Khan Date: Mon, 24 Apr 2023 11:15:35 -0600 Subject: [PATCH 1/4] add type hints --- adafruit_io/adafruit_io.py | 61 +++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index 03adf86..eb19a18 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -22,6 +22,11 @@ import json import re +try: + from typing import List, Tuple, Any +except ImportError: + pass + from adafruit_minimqtt.adafruit_minimqtt import MMQTTException from adafruit_io.adafruit_io_errors import ( AdafruitIO_RequestError, @@ -35,7 +40,7 @@ CLIENT_HEADERS = {"User-Agent": "AIO-CircuitPython/{0}".format(__version__)} -def validate_feed_key(feed_key): +def validate_feed_key(feed_key: str): """Validates a provided feed key against Adafruit IO's system rules. https://learn.adafruit.com/naming-things-in-adafruit-io/the-two-feed-identifiers """ @@ -143,7 +148,7 @@ def _on_disconnect_mqtt(self, client, userdata, return_code): self.on_disconnect(self) # pylint: disable=not-callable - def _on_message_mqtt(self, client, topic, payload): + def _on_message_mqtt(self, client, topic: str, payload: str): """Runs when the client calls on_message. Parses and returns incoming data from Adafruit IO feeds. @@ -195,7 +200,7 @@ def _on_unsubscribe_mqtt(self, client, user_data, topic, pid): if self.on_unsubscribe is not None: self.on_unsubscribe(self, user_data, topic, pid) - def add_feed_callback(self, feed_key, callback_method): + def add_feed_callback(self, feed_key: str, callback_method: str): """Attaches a callback_method to an Adafruit IO feed. The callback_method function is called when a new value is written to the feed. @@ -211,7 +216,7 @@ def add_feed_callback(self, feed_key, callback_method): "{0}/f/{1}".format(self._user, feed_key), callback_method ) - def remove_feed_callback(self, feed_key): + def remove_feed_callback(self, feed_key: str): """Removes a previously registered callback method from executing whenever feed_key receives new data. @@ -239,7 +244,7 @@ def loop(self, timeout=1): self._client.loop(timeout) # Subscriptions - def subscribe(self, feed_key=None, group_key=None, shared_user=None): + def subscribe(self, feed_key: str=None, group_key: str=None, shared_user: str=None): """Subscribes to your Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -387,7 +392,7 @@ def publish_multiple(self, feeds_and_data, timeout=3, is_group=False): time.sleep(timeout) # pylint: disable=too-many-arguments - def publish(self, feed_key, data, metadata=None, shared_user=None, is_group=False): + def publish(self, feed_key: str, data: Any, metadata: str=None, shared_use: str=None, is_group: bool=False): """Publishes to an An Adafruit IO Feed. :param str feed_key: Adafruit IO Feed key. @@ -453,7 +458,7 @@ def publish(self, feed_key, data, metadata=None, shared_user=None, is_group=Fals else: self._client.publish("{0}/f/{1}".format(self._user, feed_key), data) - def get(self, feed_key): + def get(self, feed_key: str): """Calling this method will make Adafruit IO publish the most recent value on feed_key. https://io.adafruit.com/api/docs/mqtt.html#retained-values @@ -498,7 +503,7 @@ def _create_headers(io_headers): return headers @staticmethod - def _create_data(data, metadata): + def _create_data(data, metadata: dict): """Returns a data payload as expected by the Adafruit IO HTTP API :param data: Payload value. @@ -522,7 +527,7 @@ def _handle_error(response): if response.status_code >= 400: raise AdafruitIO_RequestError(response) - def _compose_path(self, path): + def _compose_path(self, path: str): """Composes a valid API request path. :param str path: Adafruit IO API URL path. @@ -530,7 +535,7 @@ def _compose_path(self, path): return "https://io.adafruit.com/api/v2/{0}/{1}".format(self.username, path) # HTTP Requests - def _post(self, path, payload): + def _post(self, path: str, payload: json): """ POST data to Adafruit IO @@ -545,7 +550,7 @@ def _post(self, path, payload): response.close() return json_data - def _get(self, path): + def _get(self, path: str): """ GET data from Adafruit IO @@ -559,7 +564,7 @@ def _get(self, path): response.close() return json_data - def _delete(self, path): + def _delete(self, path: str): """ DELETE data from Adafruit IO. @@ -574,7 +579,7 @@ def _delete(self, path): return json_data # Data - def send_data(self, feed_key, data, metadata=None, precision=None): + def send_data(self, feed_key: str, data: str, metadata: dict=None, precision: int=None): """ Sends value data to a specified Adafruit IO feed. @@ -595,7 +600,7 @@ def send_data(self, feed_key, data, metadata=None, precision=None): payload = self._create_data(data, metadata) self._post(path, payload) - def send_batch_data(self, feed_key, data_list): + def send_batch_data(self, feed_key: str, data_list: list): """ Sends a batch array of data to a specified Adafruit IO feed @@ -607,7 +612,7 @@ def send_batch_data(self, feed_key, data_list): data_dict = type(data_list)((data._asdict() for data in data_list)) self._post(path, {"data": data_dict}) - def receive_all_data(self, feed_key): + def receive_all_data(self, feed_key: str): """ Get all data values from a specified Adafruit IO feed. Data is returned in reverse order. @@ -618,7 +623,7 @@ def receive_all_data(self, feed_key): path = self._compose_path("feeds/{0}/data".format(feed_key)) return self._get(path) - def receive_data(self, feed_key): + def receive_data(self, feed_key: str): """ Return the most recent value for the specified feed. @@ -628,7 +633,7 @@ def receive_data(self, feed_key): path = self._compose_path("feeds/{0}/data/last".format(feed_key)) return self._get(path) - def delete_data(self, feed_key, data_id): + def delete_data(self, feed_key: str, data_id: str): """ Deletes an existing Data point from a feed. @@ -640,7 +645,7 @@ def delete_data(self, feed_key, data_id): return self._delete(path) # Groups - def create_new_group(self, group_key, group_description): + def create_new_group(self, group_key:str , group_description: str): """ Creates a new Adafruit IO Group. @@ -651,7 +656,7 @@ def create_new_group(self, group_key, group_description): payload = {"name": group_key, "description": group_description} return self._post(path, payload) - def delete_group(self, group_key): + def delete_group(self, group_key: str): """ Deletes an existing group. @@ -660,7 +665,7 @@ def delete_group(self, group_key): path = self._compose_path("groups/{0}".format(group_key)) return self._delete(path) - def get_group(self, group_key): + def get_group(self, group_key: str): """ Returns Group based on Group Key @@ -669,7 +674,7 @@ def get_group(self, group_key): path = self._compose_path("groups/{0}".format(group_key)) return self._get(path) - def create_feed_in_group(self, group_key, feed_name): + def create_feed_in_group(self, group_key: str, feed_name: str): """Creates a new feed in an existing group. :param str group_key: Group name. @@ -679,7 +684,7 @@ def create_feed_in_group(self, group_key, feed_name): payload = {"feed": {"name": feed_name}} return self._post(path, payload) - def add_feed_to_group(self, group_key, feed_key): + def add_feed_to_group(self, group_key: str, feed_key: str): """ Adds an existing feed to a group @@ -692,7 +697,7 @@ def add_feed_to_group(self, group_key, feed_key): return self._post(path, payload) # Feeds - def get_feed(self, feed_key, detailed=False): + def get_feed(self, feed_key: str, detailed: bool=False): """ Returns an Adafruit IO feed based on the feed key @@ -706,7 +711,7 @@ def get_feed(self, feed_key, detailed=False): path = self._compose_path("feeds/{0}".format(feed_key)) return self._get(path) - def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): + def create_new_feed(self, feed_key: str, feed_desc: str=None, feed_license: str=None): """ Creates a new Adafruit IO feed. @@ -720,7 +725,7 @@ def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): return self._post(path, payload) def create_and_get_feed( - self, feed_key, detailed=False, feed_desc=None, feed_license=None + self, feed_key: str, detailed: bool=False, feed_desc: str=None, feed_license: str=None ): """ Attempts to return a feed; if the feed does not exist, it is created, and then returned. @@ -738,7 +743,7 @@ def create_and_get_feed( ) return self.get_feed(feed_key, detailed=detailed) - def delete_feed(self, feed_key): + def delete_feed(self, feed_key: str): """ Deletes an existing feed. @@ -749,7 +754,7 @@ def delete_feed(self, feed_key): return self._delete(path) # Adafruit IO Connected Services - def receive_weather(self, weather_id): + def receive_weather(self, weather_id: int): """ Get data from the Adafruit IO Weather Forecast Service NOTE: This service is avaliable to Adafruit IO Plus subscribers only. @@ -759,7 +764,7 @@ def receive_weather(self, weather_id): path = self._compose_path("integrations/weather/{0}".format(weather_id)) return self._get(path) - def receive_random_data(self, generator_id): + def receive_random_data(self, generator_id: int): """ Get data from the Adafruit IO Random Data Stream Service From a03f98f51f190ffb7147948003e0005b2fe842a4 Mon Sep 17 00:00:00 2001 From: Mahe Iram Khan Date: Mon, 24 Apr 2023 11:24:44 -0600 Subject: [PATCH 2/4] re-add tuple and add more typehints --- adafruit_io/adafruit_io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index eb19a18..6bd3aa4 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -289,7 +289,7 @@ def subscribe_to_errors(self): """ self._client.subscribe("%s/errors" % self._user) - def subscribe_to_randomizer(self, randomizer_id): + def subscribe_to_randomizer(self, randomizer_id: int): """Subscribes to a random data stream created by the Adafruit IO Words service. :param int randomizer_id: Random word record you want data for. @@ -298,7 +298,7 @@ def subscribe_to_randomizer(self, randomizer_id): "{0}/integration/words/{1}".format(self._user, randomizer_id) ) - def subscribe_to_weather(self, weather_record, forecast): + def subscribe_to_weather(self, weather_record: int, forecast: str): """Subscribes to a weather forecast using the Adafruit IO PLUS weather service. This feature is only avaliable to Adafruit IO PLUS subscribers. @@ -324,7 +324,7 @@ def subscribe_to_time(self, time_type): else: self._client.subscribe("time/" + time_type) - def unsubscribe(self, feed_key=None, group_key=None, shared_user=None): + def unsubscribe(self, feed_key: str=None, group_key: str=None, shared_user: str=None): """Unsubscribes from an Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -364,11 +364,11 @@ def unsubscribe(self, feed_key=None, group_key=None, shared_user=None): raise AdafruitIO_MQTTError("Must provide a feed_key or group_key.") # Publishing - def publish_multiple(self, feeds_and_data, timeout=3, is_group=False): + def publish_multiple(self, feeds_and_data: List, timeout: int=3, is_group: bool=False): """Publishes multiple data points to multiple feeds or groups with a variable timeout. - :param str feeds_and_data: List of tuples containing topic strings and data values. + :param list feeds_and_data: List of tuples containing topic strings and data values. :param int timeout: Delay between publishing data points to Adafruit IO, in seconds. :param bool is_group: Set to True if you're publishing to a group. From c7aa8885408d4355b6203f2893a37a0aa7cf4efa Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 30 May 2023 08:38:46 -0500 Subject: [PATCH 3/4] code format, pylint fixes. --- adafruit_io/adafruit_io.py | 43 ++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index 7e4c567..c81a4b0 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -23,7 +23,7 @@ import re try: - from typing import List, Tuple, Any + from typing import List, Any except ImportError: pass @@ -244,7 +244,9 @@ def loop(self, timeout=1): self._client.loop(timeout) # Subscriptions - def subscribe(self, feed_key: str=None, group_key: str=None, shared_user: str=None): + def subscribe( + self, feed_key: str = None, group_key: str = None, shared_user: str = None + ): """Subscribes to your Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -317,7 +319,9 @@ def subscribe_to_time(self, time_type): else: self._client.subscribe("time/" + time_type) - def unsubscribe(self, feed_key: str=None, group_key: str=None, shared_user: str=None): + def unsubscribe( + self, feed_key: str = None, group_key: str = None, shared_user: str = None + ): """Unsubscribes from an Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -350,7 +354,9 @@ def unsubscribe(self, feed_key: str=None, group_key: str=None, shared_user: str= raise AdafruitIO_MQTTError("Must provide a feed_key or group_key.") # Publishing - def publish_multiple(self, feeds_and_data: List, timeout: int=3, is_group: bool=False): + def publish_multiple( + self, feeds_and_data: List, timeout: int = 3, is_group: bool = False + ): """Publishes multiple data points to multiple feeds or groups with a variable timeout. @@ -378,8 +384,15 @@ def publish_multiple(self, feeds_and_data: List, timeout: int=3, is_group: bool= time.sleep(timeout) # pylint: disable=too-many-arguments - def publish(self, feed_key: str, data: Any, metadata: str=None, shared_use: str=None, is_group: bool=False): - """Publishes to an An Adafruit IO Feed. + def publish( + self, + feed_key: str, + data: Any, + metadata: str = None, + shared_user: str = None, + is_group: bool = False, + ): + """Publishes to an Adafruit IO Feed. :param str feed_key: Adafruit IO Feed key. :param str data: Data to publish to the feed or group. @@ -564,7 +577,9 @@ def _delete(self, path: str): return json_data # Data - def send_data(self, feed_key: str, data: str, metadata: dict=None, precision: int=None): + def send_data( + self, feed_key: str, data: str, metadata: dict = None, precision: int = None + ): """ Sends value data to a specified Adafruit IO feed. @@ -630,7 +645,7 @@ def delete_data(self, feed_key: str, data_id: str): return self._delete(path) # Groups - def create_new_group(self, group_key:str , group_description: str): + def create_new_group(self, group_key: str, group_description: str): """ Creates a new Adafruit IO Group. @@ -682,7 +697,7 @@ def add_feed_to_group(self, group_key: str, feed_key: str): return self._post(path, payload) # Feeds - def get_feed(self, feed_key: str, detailed: bool=False): + def get_feed(self, feed_key: str, detailed: bool = False): """ Returns an Adafruit IO feed based on the feed key @@ -696,7 +711,9 @@ def get_feed(self, feed_key: str, detailed: bool=False): path = self._compose_path("feeds/{0}".format(feed_key)) return self._get(path) - def create_new_feed(self, feed_key: str, feed_desc: str=None, feed_license: str=None): + def create_new_feed( + self, feed_key: str, feed_desc: str = None, feed_license: str = None + ): """ Creates a new Adafruit IO feed. @@ -710,7 +727,11 @@ def create_new_feed(self, feed_key: str, feed_desc: str=None, feed_license: str= return self._post(path, payload) def create_and_get_feed( - self, feed_key: str, detailed: bool=False, feed_desc: str=None, feed_license: str=None + self, + feed_key: str, + detailed: bool = False, + feed_desc: str = None, + feed_license: str = None, ): """ Attempts to return a feed; if the feed does not exist, it is created, and then returned. From d790205ba3fc90b88d33faf0f09f70563d0b6c9e Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 5 Jun 2023 14:46:40 -0500 Subject: [PATCH 4/4] typing tweaks --- adafruit_io/adafruit_io.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index c81a4b0..dfafc14 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -23,7 +23,7 @@ import re try: - from typing import List, Any + from typing import List, Any, Callable, Optional except ImportError: pass @@ -200,7 +200,7 @@ def _on_unsubscribe_mqtt(self, client, user_data, topic, pid): if self.on_unsubscribe is not None: self.on_unsubscribe(self, user_data, topic, pid) - def add_feed_callback(self, feed_key: str, callback_method: str): + def add_feed_callback(self, feed_key: str, callback_method: Callable): """Attaches a callback_method to an Adafruit IO feed. The callback_method function is called when a new value is written to the feed. @@ -245,7 +245,10 @@ def loop(self, timeout=1): # Subscriptions def subscribe( - self, feed_key: str = None, group_key: str = None, shared_user: str = None + self, + feed_key: str = None, + group_key: str = None, + shared_user: Optional[str] = None, ): """Subscribes to your Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -306,7 +309,7 @@ def subscribe_to_weather(self, weather_record: int, forecast: str): ) ) - def subscribe_to_time(self, time_type): + def subscribe_to_time(self, time_type: str): """Adafruit IO provides some built-in MQTT topics for getting the current server time. :param str time_type: Current Adafruit IO server time. Can be 'seconds', 'millis', or 'iso'. @@ -320,7 +323,10 @@ def subscribe_to_time(self, time_type): self._client.subscribe("time/" + time_type) def unsubscribe( - self, feed_key: str = None, group_key: str = None, shared_user: str = None + self, + feed_key: str = None, + group_key: str = None, + shared_user: Optional[str] = None, ): """Unsubscribes from an Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -387,7 +393,7 @@ def publish_multiple( def publish( self, feed_key: str, - data: Any, + data: str, metadata: str = None, shared_user: str = None, is_group: bool = False, @@ -534,7 +540,7 @@ def _compose_path(self, path: str): return "https://io.adafruit.com/api/v2/{0}/{1}".format(self.username, path) # HTTP Requests - def _post(self, path: str, payload: json): + def _post(self, path: str, payload: Any): """ POST data to Adafruit IO @@ -578,7 +584,11 @@ def _delete(self, path: str): # Data def send_data( - self, feed_key: str, data: str, metadata: dict = None, precision: int = None + self, + feed_key: str, + data: str, + metadata: Optional[dict] = None, + precision: Optional[int] = None, ): """ Sends value data to a specified Adafruit IO feed. @@ -712,7 +722,10 @@ def get_feed(self, feed_key: str, detailed: bool = False): return self._get(path) def create_new_feed( - self, feed_key: str, feed_desc: str = None, feed_license: str = None + self, + feed_key: str, + feed_desc: Optional[str] = None, + feed_license: Optional[str] = None, ): """ Creates a new Adafruit IO feed. @@ -730,8 +743,8 @@ def create_and_get_feed( self, feed_key: str, detailed: bool = False, - feed_desc: str = None, - feed_license: str = None, + feed_desc: Optional[str] = None, + feed_license: Optional[str] = None, ): """ Attempts to return a feed; if the feed does not exist, it is created, and then returned.