diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index c667a28..dfafc14 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, Any, Callable, Optional +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: 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. @@ -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,12 @@ 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: Optional[str] = None, + ): """Subscribes to your Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -277,7 +287,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. @@ -286,7 +296,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. @@ -299,7 +309,7 @@ def subscribe_to_weather(self, weather_record, forecast): ) ) - 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'. @@ -312,7 +322,12 @@ 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: Optional[str] = None, + ): """Unsubscribes from an Adafruit IO feed or group. Can also subscribe to someone else's feed. @@ -345,11 +360,13 @@ 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. @@ -373,8 +390,15 @@ 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): - """Publishes to an An Adafruit IO Feed. + def publish( + self, + feed_key: str, + data: str, + 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. @@ -439,7 +463,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 @@ -484,7 +508,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. @@ -508,7 +532,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. @@ -516,7 +540,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: Any): """ POST data to Adafruit IO @@ -531,7 +555,7 @@ def _post(self, path, payload): return json_data - def _get(self, path): + def _get(self, path: str): """ GET data from Adafruit IO @@ -544,7 +568,7 @@ def _get(self, path): json_data = response.json() return json_data - def _delete(self, path): + def _delete(self, path: str): """ DELETE data from Adafruit IO. @@ -559,7 +583,13 @@ 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: Optional[dict] = None, + precision: Optional[int] = None, + ): """ Sends value data to a specified Adafruit IO feed. @@ -580,7 +610,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 @@ -592,7 +622,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. @@ -603,7 +633,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. @@ -613,7 +643,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. @@ -625,7 +655,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. @@ -636,7 +666,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. @@ -645,7 +675,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 @@ -654,7 +684,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. @@ -664,7 +694,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 @@ -677,7 +707,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 @@ -691,7 +721,12 @@ 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: Optional[str] = None, + feed_license: Optional[str] = None, + ): """ Creates a new Adafruit IO feed. @@ -705,7 +740,11 @@ 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: 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. @@ -723,7 +762,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. @@ -734,7 +773,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. @@ -744,7 +783,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