diff --git a/adafruit_portalbase/__init__.py b/adafruit_portalbase/__init__.py index 953163d..457af08 100644 --- a/adafruit_portalbase/__init__.py +++ b/adafruit_portalbase/__init__.py @@ -355,9 +355,7 @@ class PortalBase: """ if self._alarm: - return self._alarm.time.TimeAlarm( - monotonic_time=time.monotonic() + sleep_time - ) + return self._alarm.time.TimeAlarm(monotonic_time=time.monotonic() + sleep_time) raise NotImplementedError( "Alarms not supported. Make sure you have the latest CircuitPython." ) diff --git a/adafruit_portalbase/graphics.py b/adafruit_portalbase/graphics.py index 1e668b1..711c7cc 100644 --- a/adafruit_portalbase/graphics.py +++ b/adafruit_portalbase/graphics.py @@ -136,9 +136,7 @@ class GraphicsBase: palette[1] = qr_color # bitmap the size of the matrix, plus border, monochrome (2 colors) - qr_bitmap = displayio.Bitmap( - qrcode.matrix.width + 2, qrcode.matrix.height + 2, 2 - ) + qr_bitmap = displayio.Bitmap(qrcode.matrix.width + 2, qrcode.matrix.height + 2, 2) for i in range(qr_bitmap.width * qr_bitmap.height): qr_bitmap[i] = 0 diff --git a/adafruit_portalbase/network.py b/adafruit_portalbase/network.py index 33937e7..9d4390d 100755 --- a/adafruit_portalbase/network.py +++ b/adafruit_portalbase/network.py @@ -38,9 +38,7 @@ __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PortalBase.git" # you'll need to pass in an io username and key -TIME_SERVICE = ( - "https://io.adafruit.com/api/v2/%s/integrations/time/strftime?x-aio-key=%s" -) +TIME_SERVICE = "https://io.adafruit.com/api/v2/%s/integrations/time/strftime?x-aio-key=%s" # our strftime is %Y-%m-%d %H:%M:%S.%L %j %u %z %Z see http://strftime.net/ for decoding details # See https://apidock.com/ruby/DateTime/strftime for full options TIME_SERVICE_FORMAT = "%Y-%m-%d %H:%M:%S.%L %j %u %z %Z" @@ -146,9 +144,7 @@ class NetworkBase: at a minimum in order to use network related features""" ) else: - print( - f"{setting_name} not found. Please add this setting to settings.toml." - ) + print(f"{setting_name} not found. Please add this setting to settings.toml.") return None def neo_status(self, value): @@ -170,16 +166,12 @@ class NetworkBase: """ value = json if not isinstance(path, (list, tuple)): - raise ValueError( - "The json_path parameter should be enclosed in a list or tuple." - ) + raise ValueError("The json_path parameter should be enclosed in a list or tuple.") for x in path: try: value = value[x] except (TypeError, KeyError, IndexError) as error: - raise ValueError( - "The specified json_path was not found in the results." - ) from error + raise ValueError("The specified json_path was not found in the results.") from error gc.collect() return value @@ -206,7 +198,7 @@ class NetworkBase: Fetch a custom strftime relative to your location. :param str location: Your city and country, e.g. ``"America/New_York"``. - :param max_attempts: The maximum number of of attempts to connect to WiFi before + :param max_attempts: The maximum number of attempts to connect to WiFi before failing or use None to disable. Defaults to 10. """ @@ -218,7 +210,9 @@ class NetworkBase: aio_key = self._get_setting("AIO_KEY") except KeyError: raise KeyError( - "\n\nOur time service requires a login/password to rate-limit. Please register for a free adafruit.io account and place the user/key in your secrets file under 'AIO_USERNAME' and 'AIO_KEY'" + "\n\nOur time service requires a login/password to rate-limit. " + "Please register for a free adafruit.io account and place the user/key " + "in your secrets file under 'AIO_USERNAME' and 'AIO_KEY'" ) from KeyError if location is None: @@ -238,8 +232,7 @@ class NetworkBase: if response.status_code != 200: print(response) error_message = ( - "Error connecting to Adafruit IO. The response was: " - + response.text + "Error connecting to Adafruit IO. The response was: " + response.text ) self.neo_status(STATUS_HTTP_ERROR) raise RuntimeError(error_message) @@ -260,16 +253,15 @@ class NetworkBase: def get_local_time(self, location=None, max_attempts=10): """ - Fetch and "set" the local time of this microcontroller to the local time at the location, using an internet time API. + Fetch and "set" the local time of this microcontroller to the local time at the location, + using an internet time API. :param str location: Your city and country, e.g. ``"America/New_York"``. - :param max_attempts: The maximum number of of attempts to connect to WiFi before + :param max_attempts: The maximum number of attempts to connect to WiFi before failing or use None to disable. Defaults to 10. """ - reply = self.get_strftime( - TIME_SERVICE_FORMAT, location=location, max_attempts=max_attempts - ) + reply = self.get_strftime(TIME_SERVICE_FORMAT, location=location, max_attempts=max_attempts) if reply: times = reply.split(" ") the_date = times[0] @@ -319,9 +311,7 @@ class NetworkBase: print("Date: {}".format(headers["date"])) self.neo_status(STATUS_HTTP_ERROR) # red = http error raise HttpError( - "Code {}: {}".format( - response.status_code, response.reason.decode("utf-8") - ), + "Code {}: {}".format(response.status_code, response.reason.decode("utf-8")), response, ) @@ -340,10 +330,7 @@ class NetworkBase: remaining -= len(i) file.write(i) if self._debug: - print( - "Read %d bytes, %d remaining" - % (content_length - remaining, remaining) - ) + print("Read %d bytes, %d remaining" % (content_length - remaining, remaining)) else: print(".", end="") if not remaining: @@ -352,9 +339,7 @@ class NetworkBase: response.close() stamp = time.monotonic() - stamp - print( - "Created file of %d bytes in %0.1f seconds" % (os.stat(filename)[6], stamp) - ) + print("Created file of %d bytes in %0.1f seconds" % (os.stat(filename)[6], stamp)) self.neo_status(STATUS_OFF) if not content_length == os.stat(filename)[6]: raise RuntimeError @@ -363,7 +348,7 @@ class NetworkBase: """ Connect to WiFi using the settings found in secrets.py - :param max_attempts: The maximum number of of attempts to connect to WiFi before + :param max_attempts: The maximum number of attempts to connect to WiFi before failing or use None to disable. Defaults to 10. """ @@ -392,19 +377,12 @@ class NetworkBase: while not self._wifi.is_connected: # secrets dictionary must contain 'ssid' and 'password' at a minimum print("Connecting to AP", secret_entry["ssid"]) - if ( - secret_entry["ssid"] == "CHANGE ME" - or secret_entry["password"] == "CHANGE ME" - ): + if secret_entry["ssid"] == "CHANGE ME" or secret_entry["password"] == "CHANGE ME": change_me = "\n" + "*" * 45 change_me += "\nPlease update the 'settings.toml' file on your\n" change_me += "CIRCUITPY drive to include your local WiFi\n" - change_me += ( - "access point SSID name in 'CIRCUITPY_WIFI_SSID' and SSID\n" - ) - change_me += ( - "password in 'CIRCUITPY_WIFI_PASSWORD'. Then save to reload!\n" - ) + change_me += "access point SSID name in 'CIRCUITPY_WIFI_SSID' and SSID\n" + change_me += "password in 'CIRCUITPY_WIFI_PASSWORD'. Then save to reload!\n" change_me += "*" * 45 raise OSError(change_me) self._wifi.neo_status(STATUS_NO_CONNECTION) # red = not connected @@ -425,9 +403,7 @@ class NetworkBase: if self._wifi.is_connected: return - raise OSError( - "Maximum number of attempts reached when trying to connect to WiFi" - ) + raise OSError("Maximum number of attempts reached when trying to connect to WiFi") def _get_io_client(self): if self._io_client is not None: @@ -609,9 +585,7 @@ class NetworkBase: print("Date: {}".format(headers["date"])) self.neo_status((100, 0, 0)) # red = http error raise HttpError( - "Code {}: {}".format( - response.status_code, response.reason.decode("utf-8") - ), + "Code {}: {}".format(response.status_code, response.reason.decode("utf-8")), response, ) diff --git a/adafruit_portalbase/wifi_esp32s2.py b/adafruit_portalbase/wifi_esp32s2.py index 1e0daa1..94ab14c 100644 --- a/adafruit_portalbase/wifi_esp32s2.py +++ b/adafruit_portalbase/wifi_esp32s2.py @@ -62,9 +62,7 @@ class WiFi: """ wifi.radio.connect(ssid, password) self.pool = socketpool.SocketPool(wifi.radio) - self.requests = adafruit_requests.Session( - self.pool, ssl.create_default_context() - ) + self.requests = adafruit_requests.Session(self.pool, ssl.create_default_context()) self._connected = True def neo_status(self, value): diff --git a/docs/conf.py b/docs/conf.py index 241b83e..3ef6e06 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -58,9 +58,7 @@ project = "Adafruit PortalBase Library" creation_year = "2020" current_year = str(datetime.datetime.now().year) year_duration = ( - current_year - if current_year == creation_year - else creation_year + " - " + current_year + current_year if current_year == creation_year else creation_year + " - " + current_year ) copyright = year_duration + " Melissa LeBlanc-Williams" author = "Melissa LeBlanc-Williams" diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..db37c83 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +target-version = "py38" +line-length = 100 + +[lint] +select = ["I", "PL", "UP"] + +extend-select = [ + "D419", # empty-docstring + "E501", # line-too-long + "W291", # trailing-whitespace + "PLC0414", # useless-import-alias + "PLC2401", # non-ascii-name + "PLC2801", # unnecessary-dunder-call + "PLC3002", # unnecessary-direct-lambda-call + "E999", # syntax-error + "PLE0101", # return-in-init + "F706", # return-outside-function + "F704", # yield-outside-function + "PLE0116", # continue-in-finally + "PLE0117", # nonlocal-without-binding + "PLE0241", # duplicate-bases + "PLE0302", # unexpected-special-method-signature + "PLE0604", # invalid-all-object + "PLE0605", # invalid-all-format + "PLE0643", # potential-index-error + "PLE0704", # misplaced-bare-raise + "PLE1141", # dict-iter-missing-items + "PLE1142", # await-outside-async + "PLE1205", # logging-too-many-args + "PLE1206", # logging-too-few-args + "PLE1307", # bad-string-format-type + "PLE1310", # bad-str-strip-call + "PLE1507", # invalid-envvar-value + "PLE2502", # bidirectional-unicode + "PLE2510", # invalid-character-backspace + "PLE2512", # invalid-character-sub + "PLE2513", # invalid-character-esc + "PLE2514", # invalid-character-nul + "PLE2515", # invalid-character-zero-width-space + "PLR0124", # comparison-with-itself + "PLR0202", # no-classmethod-decorator + "PLR0203", # no-staticmethod-decorator + "UP004", # useless-object-inheritance + "PLR0206", # property-with-parameters + "PLR0904", # too-many-public-methods + "PLR0911", # too-many-return-statements + "PLR0912", # too-many-branches + "PLR0913", # too-many-arguments + "PLR0914", # too-many-locals + "PLR0915", # too-many-statements + "PLR0916", # too-many-boolean-expressions + "PLR1702", # too-many-nested-blocks + "PLR1704", # redefined-argument-from-local + "PLR1711", # useless-return + "C416", # unnecessary-comprehension + "PLR1733", # unnecessary-dict-index-lookup + "PLR1736", # unnecessary-list-index-lookup + + # ruff reports this rule is unstable + #"PLR6301", # no-self-use + + "PLW0108", # unnecessary-lambda + "PLW0120", # useless-else-on-loop + "PLW0127", # self-assigning-variable + "PLW0129", # assert-on-string-literal + "B033", # duplicate-value + "PLW0131", # named-expr-without-context + "PLW0245", # super-without-brackets + "PLW0406", # import-self + "PLW0602", # global-variable-not-assigned + "PLW0603", # global-statement + "PLW0604", # global-at-module-level + + # fails on the try: import typing used by libraries + #"F401", # unused-import + + "F841", # unused-variable + "E722", # bare-except + "PLW0711", # binary-op-exception + "PLW1501", # bad-open-mode + "PLW1508", # invalid-envvar-default + "PLW1509", # subprocess-popen-preexec-fn + "PLW2101", # useless-with-lock + "PLW3301", # nested-min-max +] + +ignore = [ + "PLR2004", # magic-value-comparison + "UP030", # format literals + "PLW1514", # unspecified-encoding + +] + +[format] +line-ending = "lf"