diff --git a/.github/workflows/build_packages.yml b/.github/workflows/build_packages.yml index 7ac4403b6..8854a7307 100644 --- a/.github/workflows/build_packages.yml +++ b/.github/workflows/build_packages.yml @@ -9,8 +9,8 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 - name: Setup environment run: source tools/ci.sh && ci_build_packages_setup - name: Check manifest files diff --git a/.github/workflows/cleanup_published_packages.yml b/.github/workflows/cleanup_published_packages.yml index c6a33cece..040b09ff4 100644 --- a/.github/workflows/cleanup_published_packages.yml +++ b/.github/workflows/cleanup_published_packages.yml @@ -7,6 +7,6 @@ jobs: runs-on: ubuntu-latest if: vars.MICROPY_PUBLISH_MIP_INDEX steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Clean up published files run: source tools/ci.sh && ci_cleanup_package_index ${{ github.event.ref }} diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index aab347d78..7e74776af 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -6,8 +6,10 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + - uses: actions/checkout@v3 + - run: pip install --user ruff + - run: ruff --format=github . + - uses: actions/setup-python@v4 - name: Install packages run: source tools/ci.sh && ci_code_formatting_setup - name: Run code formatting diff --git a/micropython/aioespnow/aioespnow.py b/micropython/aioespnow/aioespnow.py index fb27ad7ad..c00c6fb2b 100644 --- a/micropython/aioespnow/aioespnow.py +++ b/micropython/aioespnow/aioespnow.py @@ -11,17 +11,17 @@ class AIOESPNow(espnow.ESPNow): # Read one ESPNow message async def arecv(self): yield asyncio.core._io_queue.queue_read(self) - return self.recv(0) # type: ignore + return self.recv(0) # type: ignore[misc] async def airecv(self): yield asyncio.core._io_queue.queue_read(self) - return self.irecv(0) # type: ignore + return self.irecv(0) # type: ignore[misc] async def asend(self, mac, msg=None, sync=None): if msg is None: msg, mac = mac, None # If msg is None: swap mac and msg yield asyncio.core._io_queue.queue_write(self) - return self.send(mac, msg, sync) # type: ignore + return self.send(mac, msg, sync) # type: ignore[misc] # "async for" support def __aiter__(self): diff --git a/micropython/bluetooth/aioble/examples/l2cap_file_client.py b/micropython/bluetooth/aioble/examples/l2cap_file_client.py index 02d9f6d9b..68770f043 100644 --- a/micropython/bluetooth/aioble/examples/l2cap_file_client.py +++ b/micropython/bluetooth/aioble/examples/l2cap_file_client.py @@ -87,7 +87,7 @@ async def download(self, path, dest): send_seq = await self._command(_COMMAND_SEND, path.encode()) - with open(dest, "wb") as f: + with open(dest, "wb") as f: # noqa: ASYNC101 total = 0 buf = bytearray(self._channel.our_mtu) mv = memoryview(buf) diff --git a/micropython/bluetooth/aioble/examples/l2cap_file_server.py b/micropython/bluetooth/aioble/examples/l2cap_file_server.py index b5ba27995..c3730ffd0 100644 --- a/micropython/bluetooth/aioble/examples/l2cap_file_server.py +++ b/micropython/bluetooth/aioble/examples/l2cap_file_server.py @@ -82,7 +82,7 @@ async def l2cap_task(connection): if send_file: print("Sending:", send_file) - with open(send_file, "rb") as f: + with open(send_file, "rb") as f: # noqa: ASYNC101 buf = bytearray(channel.peer_mtu) mv = memoryview(buf) while n := f.readinto(buf): diff --git a/micropython/drivers/codec/wm8960/wm8960.py b/micropython/drivers/codec/wm8960/wm8960.py index d1670220f..573fce5e9 100644 --- a/micropython/drivers/codec/wm8960/wm8960.py +++ b/micropython/drivers/codec/wm8960/wm8960.py @@ -578,7 +578,7 @@ def set_data_route(self, route): raise ValueError("Invalid route") def set_left_input(self, input): - if not input in self._input_config_table.keys(): + if input not in self._input_config_table: raise ValueError("Invalid input") input = self._input_config_table[input] @@ -595,7 +595,7 @@ def set_left_input(self, input): regs[_LINVOL] = input[1] def set_right_input(self, input): - if not input in self._input_config_table.keys(): + if input not in self._input_config_table: raise ValueError("Invalid input name") input = self._input_config_table[input] @@ -629,7 +629,7 @@ def config_data_format(self, sysclk, sample_rate, bits): self.regs[_IFACE1] = (_IFACE1_WL_MASK, wl << _IFACE1_WL_SHIFT) def volume(self, module, volume_l=None, volume_r=None): - if not module in self._volume_config_table.keys(): + if module not in self._volume_config_table: raise ValueError("Invalid module") if volume_l is None: # get volume @@ -644,7 +644,7 @@ def volume(self, module, volume_l=None, volume_r=None): if not ((0 <= volume_l <= 100) and (0 <= volume_r <= 100)): raise ValueError("Invalid value for volume") - elif not module in self._volume_config_table.keys(): + elif module not in self._volume_config_table: raise ValueError("Invalid module") vol_max, regnum, flags = self._volume_config_table[module] diff --git a/micropython/drivers/imu/bmi270/bmi270.py b/micropython/drivers/imu/bmi270/bmi270.py index 9e21b7395..db95658ff 100644 --- a/micropython/drivers/imu/bmi270/bmi270.py +++ b/micropython/drivers/imu/bmi270/bmi270.py @@ -524,13 +524,13 @@ def __init__( # Sanity checks if not self._use_i2c: raise ValueError("SPI mode is not supported") - if not gyro_odr in ODR: + if gyro_odr not in ODR: raise ValueError("Invalid gyro sampling rate: %d" % gyro_odr) - if not gyro_scale in GYRO_SCALE: + if gyro_scale not in GYRO_SCALE: raise ValueError("Invalid gyro scaling: %d" % gyro_scale) - if not accel_odr in ODR: + if accel_odr not in ODR: raise ValueError("Invalid accelerometer sampling rate: %d" % accel_odr) - if not accel_scale in ACCEL_SCALE: + if accel_scale not in ACCEL_SCALE: raise ValueError("Invalid accelerometer scaling: %d" % accel_scale) if self._read_reg(_CHIP_ID) != 0x24: raise OSError("No BMI270 device was found at address 0x%x" % (self.address)) diff --git a/micropython/drivers/imu/bmm150/bmm150.py b/micropython/drivers/imu/bmm150/bmm150.py index 12220f643..b7b4aad30 100644 --- a/micropython/drivers/imu/bmm150/bmm150.py +++ b/micropython/drivers/imu/bmm150/bmm150.py @@ -80,7 +80,7 @@ def __init__( # Sanity checks if not self._use_i2c: raise ValueError("SPI mode is not supported") - if not magnet_odr in _ODR: + if magnet_odr not in _ODR: raise ValueError("Invalid sampling rate: %d" % magnet_odr) # Perform soft reset, and power on. diff --git a/micropython/drivers/imu/lsm6dsox/lsm6dsox.py b/micropython/drivers/imu/lsm6dsox/lsm6dsox.py index 2e043f24c..1e4267ae7 100644 --- a/micropython/drivers/imu/lsm6dsox/lsm6dsox.py +++ b/micropython/drivers/imu/lsm6dsox/lsm6dsox.py @@ -130,20 +130,20 @@ def __init__( accel_odr = round(accel_odr, 2) # Sanity checks - if not gyro_odr in ODR: + if gyro_odr not in ODR: raise ValueError("Invalid sampling rate: %d" % gyro_odr) - if not gyro_scale in SCALE_GYRO: + if gyro_scale not in SCALE_GYRO: raise ValueError("invalid gyro scaling: %d" % gyro_scale) - if not accel_odr in ODR: + if accel_odr not in ODR: raise ValueError("Invalid sampling rate: %d" % accel_odr) - if not accel_scale in SCALE_ACCEL: + if accel_scale not in SCALE_ACCEL: raise ValueError("invalid accelerometer scaling: %d" % accel_scale) # Soft-reset the device. self.reset() # Load and configure MLC if UCF file is provided - if ucf != None: + if ucf is not None: self.load_mlc(ucf) # Set Gyroscope datarate and scale. diff --git a/micropython/drivers/imu/lsm6dsox/lsm6dsox_mlc.py b/micropython/drivers/imu/lsm6dsox/lsm6dsox_mlc.py index ce3ff8e92..2a53b9402 100644 --- a/micropython/drivers/imu/lsm6dsox/lsm6dsox_mlc.py +++ b/micropython/drivers/imu/lsm6dsox/lsm6dsox_mlc.py @@ -17,7 +17,7 @@ def imu_int_handler(pin): INT_FLAG = True -if INT_MODE == True: +if INT_MODE is True: int_pin = Pin(24) int_pin.irq(handler=imu_int_handler, trigger=Pin.IRQ_RISING) @@ -44,5 +44,5 @@ def imu_int_handler(pin): print(UCF_LABELS[lsm.mlc_output()[0]]) else: buf = lsm.mlc_output() - if buf != None: + if buf is not None: print(UCF_LABELS[buf[0]]) diff --git a/micropython/drivers/imu/lsm9ds1/lsm9ds1.py b/micropython/drivers/imu/lsm9ds1/lsm9ds1.py index 8042ecc6f..7123a574b 100644 --- a/micropython/drivers/imu/lsm9ds1/lsm9ds1.py +++ b/micropython/drivers/imu/lsm9ds1/lsm9ds1.py @@ -95,19 +95,19 @@ def __init__( self.address_magnet = address_magnet # Sanity checks - if not gyro_odr in _ODR_IMU: + if gyro_odr not in _ODR_IMU: raise ValueError("Invalid gyro sampling rate: %d" % gyro_odr) - if not gyro_scale in _GYRO_SCALE: + if gyro_scale not in _GYRO_SCALE: raise ValueError("Invalid gyro scaling: %d" % gyro_scale) - if not accel_odr in _ODR_IMU: + if accel_odr not in _ODR_IMU: raise ValueError("Invalid accelerometer sampling rate: %d" % accel_odr) - if not accel_scale in _ACCEL_SCALE: + if accel_scale not in _ACCEL_SCALE: raise ValueError("Invalid accelerometer scaling: %d" % accel_scale) - if not magnet_odr in _ODR_MAGNET: + if magnet_odr not in _ODR_MAGNET: raise ValueError("Invalid magnet sampling rate: %d" % magnet_odr) - if not magnet_scale in _MAGNET_SCALE: + if magnet_scale not in _MAGNET_SCALE: raise ValueError("Invalid magnet scaling: %d" % magnet_scale) if (self.magent_id() != b"=") or (self.gyro_id() != b"h"): diff --git a/micropython/lora/examples/simple_rxtx/simple_rxtx.py b/micropython/lora/examples/simple_rxtx/simple_rxtx.py index 858570bc1..a5602b655 100644 --- a/micropython/lora/examples/simple_rxtx/simple_rxtx.py +++ b/micropython/lora/examples/simple_rxtx/simple_rxtx.py @@ -40,7 +40,7 @@ def main(): print("Receiving...") rx = modem.recv(timeout_ms=5000) if rx: - print(f"Received: {repr(rx)}") + print(f"Received: {rx!r}") else: print("Timeout!") time.sleep(2) diff --git a/micropython/lora/examples/simple_rxtx/simple_rxtx_async.py b/micropython/lora/examples/simple_rxtx/simple_rxtx_async.py index f297059a5..9504aad48 100644 --- a/micropython/lora/examples/simple_rxtx/simple_rxtx_async.py +++ b/micropython/lora/examples/simple_rxtx/simple_rxtx_async.py @@ -41,7 +41,7 @@ async def recv_coro(modem): print("Receiving...") rx = await modem.recv(2000) if rx: - print(f"Received: {repr(rx)}") + print(f"Received: {rx!r}") else: print("Receive timeout!") diff --git a/micropython/lora/lora-sx126x/lora/sx126x.py b/micropython/lora/lora-sx126x/lora/sx126x.py index ada3616c6..7fbcce2f5 100644 --- a/micropython/lora/lora-sx126x/lora/sx126x.py +++ b/micropython/lora/lora-sx126x/lora/sx126x.py @@ -487,7 +487,7 @@ def calibrate_image(self): else: # DS says "Contact your Semtech representative for the other optimal # calibration settings outside of the given frequency bands" - raise ValueError() + raise ValueError self._cmd(">BH", _CMD_CALIBRATE_IMAGE, args) diff --git a/micropython/lora/lora/lora/modem.py b/micropython/lora/lora/lora/modem.py index 62313dc04..bb9b0c07d 100644 --- a/micropython/lora/lora/lora/modem.py +++ b/micropython/lora/lora/lora/modem.py @@ -282,7 +282,7 @@ def start_recv(self, timeout_ms=None, continuous=False, rx_length=0xFF): # # Part of common low-level modem API, see README.md for usage. if continuous and timeout_ms is not None: - raise ValueError() # these two options are mutually exclusive + raise ValueError # these two options are mutually exclusive if timeout_ms is not None: self._rx = time.ticks_add(time.ticks_ms(), timeout_ms) diff --git a/micropython/senml/examples/custom_record.py b/micropython/senml/examples/custom_record.py index e754c897c..e68d05f5b 100644 --- a/micropython/senml/examples/custom_record.py +++ b/micropython/senml/examples/custom_record.py @@ -43,7 +43,7 @@ def __init__(self, name, **kwargs): def _check_value_type(self, value): """overriding the check on value type to make certain that only an array with 3 values is assigned: lat,lon/alt""" - if not value == None: + if value is not None: if not isinstance(value, list): raise Exception("invalid data type: array with 3 elements expected lat, lon, alt") diff --git a/micropython/senml/examples/gateway_actuators.py b/micropython/senml/examples/gateway_actuators.py index ae8514395..add5ed24c 100644 --- a/micropython/senml/examples/gateway_actuators.py +++ b/micropython/senml/examples/gateway_actuators.py @@ -56,7 +56,7 @@ def gateway_callback(record, **kwargs): :param kwargs: optional extra parameters (device can be found here) :return: None """ - if "device" in kwargs and kwargs["device"] != None: + if "device" in kwargs and kwargs["device"] is not None: print("for device: " + kwargs["device"].name) else: print("for gateway: ") diff --git a/micropython/senml/senml/senml_pack.py b/micropython/senml/senml/senml_pack.py index d528911ff..85b26d40b 100644 --- a/micropython/senml/senml/senml_pack.py +++ b/micropython/senml/senml/senml_pack.py @@ -47,7 +47,7 @@ def __next__(self): self._index += 1 return res else: - raise StopIteration() + raise StopIteration class SenmlPack(SenmlBase): @@ -156,7 +156,7 @@ def _check_value_type(self, value, field_name): checks if the type of value is allowed for senml :return: None, raisee exception if not ok. """ - if not value == None: + if value is not None: if not (isinstance(value, int) or isinstance(value, float)): raise Exception("invalid type for " + field_name + ", only numbers allowed") @@ -330,7 +330,7 @@ def add(self, item): """ if not (isinstance(item, SenmlBase)): raise Exception("invalid type of param, SenmlRecord or SenmlPack expected") - if not item._parent == None: + if item._parent is not None: raise Exception("item is already part of a pack") self._data.append(item) diff --git a/micropython/senml/senml/senml_record.py b/micropython/senml/senml/senml_record.py index fe7c56c46..9dfe22873 100644 --- a/micropython/senml/senml/senml_record.py +++ b/micropython/senml/senml/senml_record.py @@ -79,7 +79,7 @@ def _check_value_type(self, value): checks if the type of value is allowed for senml :return: None, raisee exception if not ok. """ - if not value == None: + if value is not None: if not ( isinstance(value, bool) or isinstance(value, int) @@ -96,7 +96,7 @@ def _check_number_type(self, value, field_name): checks if the type of value is allowed for senml :return: None, raisee exception if not ok. """ - if not value == None: + if value is not None: if not (isinstance(value, int) or isinstance(value, float)): raise Exception("invalid type for " + field_name + ", only numbers allowed") diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..6828563c9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,93 @@ +[tool.ruff] +exclude = [ + "python-stdlib", + "unix-ffi", +] +select = [ + "ASYNC", # flake8-comprehensions + "C4", # flake8-comprehensions + "C90", # McCabe cyclomatic complexity + "DTZ", # flake8-datetimez + "E", # pycodestyle + "EXE", # flake8-executable + "F", # Pyflakes + "G", # flake8-logging-format + "ICN", # flake8-import-conventions + "INT", # flake8-gettext + "ISC", # flake8-implicit-str-concat + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # Pylint + "PYI", # flake8-pyi + "RSE", # flake8-raise + "RUF", # Ruff-specific rules + "T10", # flake8-debugger + "TCH", # flake8-type-checking + "W", # pycodestyle + "YTT", # flake8-2020 + # "A", # flake8-builtins + # "ANN", # flake8-annotations + # "ARG", # flake8-unused-arguments + # "B", # flake8-bugbear + # "BLE", # flake8-blind-except + # "COM", # flake8-commas + # "D", # pydocstyle + # "DJ", # flake8-django + # "EM", # flake8-errmsg + # "ERA", # eradicate + # "FBT", # flake8-boolean-trap + # "I", # isort + # "INP", # flake8-no-pep420 + # "N", # pep8-naming + # "NPY", # NumPy-specific rules + # "PD", # pandas-vet + # "PT", # flake8-pytest-style + # "PTH", # flake8-use-pathlib + # "Q", # flake8-quotes + # "RET", # flake8-return + # "S", # flake8-bandit + # "SIM", # flake8-simplify + # "SLF", # flake8-self + # "T20", # flake8-print + # "TID", # flake8-tidy-imports + # "TRY", # tryceratops + # "UP", # pyupgrade +] +ignore = [ + "E401", + "E402", + "E722", + "E741", + "F401", + "F403", + "F405", + "F541", + "F821", + "F841", + "ISC003", # micropython does not support implicit concatenation of f-strings + "PIE810", # micropython does not support passing tuples to .startswith or .endswith + "PLC1901", + "PLR1701", + "PLR1714", + "PLR5501", + "PLW0602", + "PLW0603", + "PLW2901", + "RUF012", + "RUF100", +] +line-length = 260 +target-version = "py37" + +[tool.ruff.mccabe] +max-complexity = 61 + +[tool.ruff.pylint] +allow-magic-value-types = ["bytes", "int", "str"] +max-args = 14 +max-branches = 58 +max-returns = 13 +max-statements = 166 + +[tool.ruff.per-file-ignores] +"micropython/aiorepl/aiorepl.py" = ["PGH001"] diff --git a/python-ecosys/cbor2/cbor2/encoder.py b/python-ecosys/cbor2/cbor2/encoder.py index d739cea40..80a4ac022 100644 --- a/python-ecosys/cbor2/cbor2/encoder.py +++ b/python-ecosys/cbor2/cbor2/encoder.py @@ -25,7 +25,6 @@ import io -import math import struct diff --git a/python-ecosys/iperf3/iperf3.py b/python-ecosys/iperf3/iperf3.py index 614bc6193..71e4dae17 100644 --- a/python-ecosys/iperf3/iperf3.py +++ b/python-ecosys/iperf3/iperf3.py @@ -156,7 +156,6 @@ def report_receiver(self, stats): st["errors"], " receiver", ) - return def recvn(s, n): diff --git a/python-ecosys/requests/requests/__init__.py b/python-ecosys/requests/requests/__init__.py index e1998711d..56b4a4f49 100644 --- a/python-ecosys/requests/requests/__init__.py +++ b/python-ecosys/requests/requests/__init__.py @@ -92,7 +92,7 @@ def request( if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - if not "Host" in headers: + if "Host" not in headers: s.write(b"Host: %s\r\n" % host) # Iterate over keys to avoid tuple alloc for k in headers: