From 302008356471506fdd37d9a0cbe2548642cbaa15 Mon Sep 17 00:00:00 2001 From: Katherine Whitlock Date: Wed, 19 Feb 2025 14:24:43 -0500 Subject: [PATCH] Ruff format for CI (#8276) --- .github/workflows/ci.yml | 12 ++++---- .pre-commit-config.yaml | 2 +- esphome/__main__.py | 2 +- esphome/components/climate/__init__.py | 1 - .../components/esp32_ble_beacon/__init__.py | 4 ++- esphome/components/esp8266/gpio.py | 3 +- esphome/components/haier/climate.py | 23 +++++++------- esphome/components/mqtt/__init__.py | 4 +-- .../components/nfc/binary_sensor/__init__.py | 8 ++--- .../opentherm/binary_sensor/__init__.py | 8 ++--- esphome/components/opentherm/generate.py | 12 ++++---- .../components/opentherm/sensor/__init__.py | 11 ++++--- esphome/components/pn532/binary_sensor.py | 8 ++--- esphome/components/rc522/binary_sensor.py | 8 ++--- esphome/components/thermostat/climate.py | 2 +- esphome/config_validation.py | 3 +- esphome/cpp_generator.py | 6 ++-- esphome/wizard.py | 30 ++++++++----------- esphome/writer.py | 4 +-- requirements_test.txt | 2 +- tests/unit_tests/test_cpp_generator.py | 9 ++---- 21 files changed, 75 insertions(+), 87 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd79356b3c..59dc31e9f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,8 +61,8 @@ jobs: pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt pip install -e . - black: - name: Check black + ruff: + name: Check ruff runs-on: ubuntu-24.04 needs: - common @@ -74,10 +74,10 @@ jobs: with: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run black + - name: Run Ruff run: | . venv/bin/activate - black --verbose esphome tests + ruff format esphome tests - name: Suggested changes run: script/ci-suggest-changes if: always() @@ -255,7 +255,7 @@ jobs: runs-on: ubuntu-24.04 needs: - common - - black + - ruff - ci-custom - clang-format - flake8 @@ -482,7 +482,7 @@ jobs: runs-on: ubuntu-24.04 needs: - common - - black + - ruff - ci-custom - clang-format - flake8 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 212d822ff8..667a8f2e8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.5.4 + rev: v0.9.2 hooks: # Run the linter. - id: ruff diff --git a/esphome/__main__.py b/esphome/__main__.py index 2a0bd8f2b3..770c1a8fcf 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -66,7 +66,7 @@ def choose_prompt(options, purpose: str = None): return options[0][1] safe_print( - f'Found multiple options{f" for {purpose}" if purpose else ""}, please choose one:' + f"Found multiple options{f' for {purpose}' if purpose else ''}, please choose one:" ) for i, (desc, _) in enumerate(options): safe_print(f" [{i + 1}] {desc}") diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index aa705e7332..445507c620 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -128,7 +128,6 @@ VISUAL_TEMPERATURE_STEP_SCHEMA = cv.Schema( def visual_temperature_step(value): - # Allow defining target/current temperature steps separately if isinstance(value, dict): return VISUAL_TEMPERATURE_STEP_SCHEMA(value) diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index f97f289a0a..6e0d103aa0 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -66,7 +66,9 @@ FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant async def to_code(config): uuid = config[CONF_UUID].hex - uuid_arr = [cg.RawExpression(f"0x{uuid[i:i + 2]}") for i in range(0, len(uuid), 2)] + uuid_arr = [ + cg.RawExpression(f"0x{uuid[i : i + 2]}") for i in range(0, len(uuid), 2) + ] var = cg.new_Pvariable(config[CONF_ID], uuid_arr) parent = await cg.get_variable(config[esp32_ble.CONF_BLE_ID]) diff --git a/esphome/components/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index 53016d2130..050efaacae 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -112,8 +112,7 @@ def validate_supports(value): ) if is_pullup and num == 16: raise cv.Invalid( - "GPIO Pin 16 does not support pullup pin mode. " - "Please choose another pin.", + "GPIO Pin 16 does not support pullup pin mode. Please choose another pin.", [CONF_MODE, CONF_PULLUP], ) if is_pulldown and num != 16: diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index f2dc7174cb..f77d624649 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -1,9 +1,15 @@ -import logging -import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv -from esphome.components import uart, climate, logger +import logging + from esphome import automation +import esphome.codegen as cg +from esphome.components import climate, logger, uart +from esphome.components.climate import ( + CONF_CURRENT_TEMPERATURE, + ClimateMode, + ClimatePreset, + ClimateSwingMode, +) +import esphome.config_validation as cv from esphome.const import ( CONF_BEEPER, CONF_DISPLAY, @@ -24,12 +30,7 @@ from esphome.const import ( CONF_VISUAL, CONF_WIFI, ) -from esphome.components.climate import ( - ClimateMode, - ClimatePreset, - ClimateSwingMode, - CONF_CURRENT_TEMPERATURE, -) +import esphome.final_validate as fv _LOGGER = logging.getLogger(__name__) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index e1002478a1..99f8ad76d8 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -36,6 +36,7 @@ from esphome.const import ( CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, + CONF_PUBLISH_NAN_AS_NONE, CONF_QOS, CONF_REBOOT_TIMEOUT, CONF_RETAIN, @@ -49,7 +50,6 @@ from esphome.const import ( CONF_USE_ABBREVIATIONS, CONF_USERNAME, CONF_WILL_MESSAGE, - CONF_PUBLISH_NAN_AS_NONE, PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, @@ -406,7 +406,7 @@ async def to_code(config): if CONF_SSL_FINGERPRINTS in config: for fingerprint in config[CONF_SSL_FINGERPRINTS]: arr = [ - cg.RawExpression(f"0x{fingerprint[i:i + 2]}") for i in range(0, 40, 2) + cg.RawExpression(f"0x{fingerprint[i : i + 2]}") for i in range(0, 40, 2) ] cg.add(var.add_ssl_fingerprint(arr)) cg.add_build_flag("-DASYNC_TCP_SSL_ENABLED=1") diff --git a/esphome/components/nfc/binary_sensor/__init__.py b/esphome/components/nfc/binary_sensor/__init__.py index 21c8298ea8..47cf014550 100644 --- a/esphome/components/nfc/binary_sensor/__init__.py +++ b/esphome/components/nfc/binary_sensor/__init__.py @@ -1,9 +1,10 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import binary_sensor +import esphome.config_validation as cv from esphome.const import CONF_UID from esphome.core import HexInt -from .. import nfc_ns, Nfcc, NfcTagListener + +from .. import Nfcc, NfcTagListener, nfc_ns DEPENDENCIES = ["nfc"] @@ -25,8 +26,7 @@ def validate_uid(value): for x in value.split("-"): if len(x) != 2: raise cv.Invalid( - "Each part (separated by '-') of the UID must be two characters " - "long." + "Each part (separated by '-') of the UID must be two characters long." ) try: x = int(x, 16) diff --git a/esphome/components/opentherm/binary_sensor/__init__.py b/esphome/components/opentherm/binary_sensor/__init__.py index 643734f90c..d4c7861a1d 100644 --- a/esphome/components/opentherm/binary_sensor/__init__.py +++ b/esphome/components/opentherm/binary_sensor/__init__.py @@ -1,8 +1,9 @@ from typing import Any -import esphome.config_validation as cv from esphome.components import binary_sensor -from .. import const, schema, validate, generate +import esphome.config_validation as cv + +from .. import const, generate, schema, validate DEPENDENCIES = [const.OPENTHERM] COMPONENT_TYPE = const.BINARY_SENSOR @@ -11,8 +12,7 @@ COMPONENT_TYPE = const.BINARY_SENSOR def get_entity_validation_schema(entity: schema.BinarySensorSchema) -> cv.Schema: return binary_sensor.binary_sensor_schema( device_class=( - entity.device_class - or binary_sensor._UNDEF # pylint: disable=protected-access + entity.device_class or binary_sensor._UNDEF # pylint: disable=protected-access ), icon=(entity.icon or binary_sensor._UNDEF), # pylint: disable=protected-access ) diff --git a/esphome/components/opentherm/generate.py b/esphome/components/opentherm/generate.py index 6b6a0255a8..a97754d52c 100644 --- a/esphome/components/opentherm/generate.py +++ b/esphome/components/opentherm/generate.py @@ -3,8 +3,9 @@ from typing import Any, Callable, Optional import esphome.codegen as cg from esphome.const import CONF_ID + from . import const -from .schema import TSchema, SettingSchema +from .schema import SettingSchema, TSchema opentherm_ns = cg.esphome_ns.namespace("opentherm") OpenthermHub = opentherm_ns.class_("OpenthermHub", cg.Component) @@ -112,11 +113,10 @@ def add_messages(hub: cg.MockObj, keys: list[str], schemas: dict[str, TSchema]): msg_expr = cg.RawExpression(f"esphome::opentherm::MessageId::{msg}") if keep_updated: cg.add(hub.add_repeating_message(msg_expr)) + elif order is not None: + cg.add(hub.add_initial_message(msg_expr, order)) else: - if order is not None: - cg.add(hub.add_initial_message(msg_expr, order)) - else: - cg.add(hub.add_initial_message(msg_expr)) + cg.add(hub.add_initial_message(msg_expr)) def add_property_set(var: cg.MockObj, config_key: str, config: dict[str, Any]) -> None: @@ -128,7 +128,7 @@ Create = Callable[[dict[str, Any], str, cg.MockObj], Awaitable[cg.Pvariable]] def create_only_conf( - create: Callable[[dict[str, Any]], Awaitable[cg.Pvariable]] + create: Callable[[dict[str, Any]], Awaitable[cg.Pvariable]], ) -> Create: return lambda conf, _key, _hub: create(conf) diff --git a/esphome/components/opentherm/sensor/__init__.py b/esphome/components/opentherm/sensor/__init__.py index 546a79054b..86c842b299 100644 --- a/esphome/components/opentherm/sensor/__init__.py +++ b/esphome/components/opentherm/sensor/__init__.py @@ -1,8 +1,9 @@ from typing import Any -import esphome.config_validation as cv from esphome.components import sensor -from .. import const, schema, validate, generate +import esphome.config_validation as cv + +from .. import const, generate, schema, validate DEPENDENCIES = [const.OPENTHERM] COMPONENT_TYPE = const.SENSOR @@ -22,11 +23,9 @@ MSG_DATA_TYPES = { def get_entity_validation_schema(entity: schema.SensorSchema) -> cv.Schema: return sensor.sensor_schema( - unit_of_measurement=entity.unit_of_measurement - or sensor._UNDEF, # pylint: disable=protected-access + unit_of_measurement=entity.unit_of_measurement or sensor._UNDEF, # pylint: disable=protected-access accuracy_decimals=entity.accuracy_decimals, - device_class=entity.device_class - or sensor._UNDEF, # pylint: disable=protected-access + device_class=entity.device_class or sensor._UNDEF, # pylint: disable=protected-access icon=entity.icon or sensor._UNDEF, # pylint: disable=protected-access state_class=entity.state_class, ).extend( diff --git a/esphome/components/pn532/binary_sensor.py b/esphome/components/pn532/binary_sensor.py index 9bcae30750..b9c3103c65 100644 --- a/esphome/components/pn532/binary_sensor.py +++ b/esphome/components/pn532/binary_sensor.py @@ -1,9 +1,10 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import binary_sensor +import esphome.config_validation as cv from esphome.const import CONF_UID from esphome.core import HexInt -from . import pn532_ns, PN532, CONF_PN532_ID + +from . import CONF_PN532_ID, PN532, pn532_ns DEPENDENCIES = ["pn532"] @@ -13,8 +14,7 @@ def validate_uid(value): for x in value.split("-"): if len(x) != 2: raise cv.Invalid( - "Each part (separated by '-') of the UID must be two characters " - "long." + "Each part (separated by '-') of the UID must be two characters long." ) try: x = int(x, 16) diff --git a/esphome/components/rc522/binary_sensor.py b/esphome/components/rc522/binary_sensor.py index 716c0eca76..87f81c2223 100644 --- a/esphome/components/rc522/binary_sensor.py +++ b/esphome/components/rc522/binary_sensor.py @@ -1,9 +1,10 @@ import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import binary_sensor +import esphome.config_validation as cv from esphome.const import CONF_UID from esphome.core import HexInt -from . import rc522_ns, RC522, CONF_RC522_ID + +from . import CONF_RC522_ID, RC522, rc522_ns DEPENDENCIES = ["rc522"] @@ -13,8 +14,7 @@ def validate_uid(value): for x in value.split("-"): if len(x) != 2: raise cv.Invalid( - "Each part (separated by '-') of the UID must be two characters " - "long." + "Each part (separated by '-') of the UID must be two characters long." ) try: x = int(x, 16) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index a529bbd474..638aad7c06 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -137,7 +137,7 @@ def validate_temperature_preset(preset, root_config, name, requirements): def generate_comparable_preset(config, name): - comparable_preset = f"{CONF_PRESET}:\n" f" - {CONF_NAME}: {name}\n" + comparable_preset = f"{CONF_PRESET}:\n - {CONF_NAME}: {name}\n" if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config: comparable_preset += f" {CONF_DEFAULT_TARGET_TEMPERATURE_LOW}: {config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW]}\n" diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 27d11e4ded..9f7ce4d2e3 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1223,8 +1223,7 @@ def subscribe_topic(value): if index != len(value) - 1: # If there are multiple wildcards, this will also trigger raise Invalid( - "Multi-level wildcard must be the last " - "character in the topic filter." + "Multi-level wildcard must be the last character in the topic filter." ) if len(value) > 1 and value[index - 1] != "/": raise Invalid("Multi-level wildcard must be after a topic level separator.") diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 4e283868e1..eb0bd25d1d 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -506,9 +506,9 @@ def with_local_variable(id_: ID, rhs: SafeExpType, callback: Callable, *args) -> """ # throw if the callback is async: - assert not inspect.iscoroutinefunction( - callback - ), "with_local_variable() callback cannot be async!" + assert not inspect.iscoroutinefunction(callback), ( + "with_local_variable() callback cannot be async!" + ) CORE.add(RawStatement("{")) # output opening curly brace obj = variable(id_, rhs, None, True) diff --git a/esphome/wizard.py b/esphome/wizard.py index eecbbdb172..7fdf245c76 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -144,17 +144,17 @@ def wizard_file(**kwargs): # Configure API if "password" in kwargs: - config += f" password: \"{kwargs['password']}\"\n" + config += f' password: "{kwargs["password"]}"\n' if "api_encryption_key" in kwargs: - config += f" encryption:\n key: \"{kwargs['api_encryption_key']}\"\n" + config += f' encryption:\n key: "{kwargs["api_encryption_key"]}"\n' # Configure OTA config += "\nota:\n" config += " - platform: esphome\n" if "ota_password" in kwargs: - config += f" password: \"{kwargs['ota_password']}\"" + config += f' password: "{kwargs["ota_password"]}"' elif "password" in kwargs: - config += f" password: \"{kwargs['password']}\"" + config += f' password: "{kwargs["password"]}"' # Configuring wifi config += "\n\nwifi:\n" @@ -181,18 +181,14 @@ def wizard_file(**kwargs): password: "{fallback_psk}" captive_portal: - """.format( - **kwargs - ) + """.format(**kwargs) else: config += """ # Enable fallback hotspot in case wifi connection fails ap: ssid: "{fallback_name}" password: "{fallback_psk}" - """.format( - **kwargs - ) + """.format(**kwargs) return config @@ -388,19 +384,19 @@ def wizard(path): safe_print() # Don't sleep because user needs to copy link if platform == "ESP32": - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcu-32s')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "nodemcu-32s")}".') boards_list = esp32_boards.BOARDS.items() elif platform == "ESP8266": - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcuv2')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "nodemcuv2")}".') boards_list = esp8266_boards.BOARDS.items() elif platform == "BK72XX": - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'cb2s')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "cb2s")}".') boards_list = bk72xx_boards.BOARDS.items() elif platform == "RTL87XX": - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'wr3')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "wr3")}".') boards_list = rtl87xx_boards.BOARDS.items() elif platform == "RP2040": - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'rpipicow')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "rpipicow")}".') boards_list = rp2040_boards.BOARDS.items() else: @@ -439,7 +435,7 @@ def wizard(path): f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?" ) sleep(1.5) - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "Abraham Linksys")}".') while True: ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) try: @@ -465,7 +461,7 @@ def wizard(path): f"Now please state the {color(Fore.GREEN, 'password')} of the WiFi network so that I can connect to it (Leave empty for no password)" ) safe_print() - safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") + safe_print(f'For example "{color(Fore.BOLD_WHITE, "PASSWORD42")}"') sleep(0.5) psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): ")) safe_print( diff --git a/esphome/writer.py b/esphome/writer.py index 90446ae4b1..39423db64c 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -212,9 +212,7 @@ def write_platformio_project(): write_platformio_ini(content) -DEFINES_H_FORMAT = ( - ESPHOME_H_FORMAT -) = """\ +DEFINES_H_FORMAT = ESPHOME_H_FORMAT = """\ #pragma once #include "esphome/core/macros.h" {} diff --git a/requirements_test.txt b/requirements_test.txt index 5d94f7f640..d836efc148 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==3.2.7 flake8==7.0.0 # also change in .pre-commit-config.yaml when updating -black==24.4.2 # also change in .pre-commit-config.yaml when updating +ruff==0.9.2 # also change in .pre-commit-config.yaml when updating pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating pre-commit diff --git a/tests/unit_tests/test_cpp_generator.py b/tests/unit_tests/test_cpp_generator.py index 6f4b5a40bc..95633ca0c6 100644 --- a/tests/unit_tests/test_cpp_generator.py +++ b/tests/unit_tests/test_cpp_generator.py @@ -1,11 +1,9 @@ from collections.abc import Iterator - import math import pytest -from esphome import cpp_generator as cg -from esphome import cpp_types as ct +from esphome import cpp_generator as cg, cpp_types as ct class TestExpressions: @@ -156,10 +154,7 @@ class TestLambdaExpression: actual = str(target) assert actual == ( - "[=](int32_t foo, float bar) {\n" - " if ((foo == 5) && (bar < 10))) {\n" - " }\n" - "}" + "[=](int32_t foo, float bar) {\n if ((foo == 5) && (bar < 10))) {\n }\n}" ) def test_str__with_return(self):