From dbb195691b0ad784ac84d0273b48a69d31bad27c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Sep 2021 19:22:28 +0200 Subject: [PATCH] Bump pylint from 2.10.2 to 2.11.1 (#2334) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Otto winter --- esphome/__main__.py | 14 +-- esphome/components/binary_sensor/__init__.py | 16 ++-- esphome/components/deep_sleep/__init__.py | 3 +- .../components/esp32_ble_beacon/__init__.py | 4 +- .../components/esp32_ble_tracker/__init__.py | 13 +-- esphome/components/font/__init__.py | 5 +- esphome/components/lcd_gpio/display.py | 3 +- esphome/components/ledc/output.py | 6 +- esphome/components/light/effects.py | 6 +- esphome/components/logger/__init__.py | 8 +- esphome/components/mqtt/__init__.py | 7 +- esphome/components/neopixelbus/light.py | 8 +- esphome/components/nextion/base_component.py | 6 +- esphome/components/ntc/sensor.py | 4 +- esphome/components/packages/__init__.py | 3 +- esphome/components/partition/light.py | 3 +- esphome/components/pmsx003/sensor.py | 4 +- esphome/components/remote_base/__init__.py | 16 ++-- esphome/components/rotary_encoder/sensor.py | 3 +- esphome/components/sensor/__init__.py | 6 +- esphome/components/substitutions/__init__.py | 7 +- esphome/components/time/__init__.py | 36 +++----- esphome/components/wifi/wpa2_eap.py | 1 + esphome/config.py | 76 ++++++---------- esphome/config_validation.py | 89 +++++++------------ esphome/core/__init__.py | 18 ++-- esphome/core/config.py | 15 +--- esphome/cpp_generator.py | 12 ++- esphome/cpp_helpers.py | 4 +- esphome/dashboard/dashboard.py | 46 +++++----- esphome/espota2.py | 6 +- esphome/helpers.py | 8 +- esphome/mqtt.py | 9 +- esphome/pins.py | 15 ++-- esphome/platformio_api.py | 16 ++-- esphome/storage_json.py | 4 +- esphome/wizard.py | 84 ++++++----------- esphome/writer.py | 10 +-- esphome/yaml_util.py | 7 +- requirements_test.txt | 2 +- 40 files changed, 219 insertions(+), 384 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 121fa7cc9e..ba1019869d 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -72,7 +72,7 @@ def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api if default == "OTA": return CORE.address if show_mqtt and "mqtt" in CORE.config: - options.append(("MQTT ({})".format(CORE.config["mqtt"][CONF_BROKER]), "MQTT")) + options.append((f"MQTT ({CORE.config['mqtt'][CONF_BROKER]})", "MQTT")) if default == "OTA": return "MQTT" if default is not None: @@ -415,30 +415,30 @@ def command_update_all(args): click.echo(f"{half_line}{middle_text}{half_line}") for f in files: - print("Updating {}".format(color(Fore.CYAN, f))) + print(f"Updating {color(Fore.CYAN, f)}") print("-" * twidth) print() rc = run_external_process( "esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA" ) if rc == 0: - print_bar("[{}] {}".format(color(Fore.BOLD_GREEN, "SUCCESS"), f)) + print_bar(f"[{color(Fore.BOLD_GREEN, 'SUCCESS')}] {f}") success[f] = True else: - print_bar("[{}] {}".format(color(Fore.BOLD_RED, "ERROR"), f)) + print_bar(f"[{color(Fore.BOLD_RED, 'ERROR')}] {f}") success[f] = False print() print() print() - print_bar("[{}]".format(color(Fore.BOLD_WHITE, "SUMMARY"))) + print_bar(f"[{color(Fore.BOLD_WHITE, 'SUMMARY')}]") failed = 0 for f in files: if success[f]: - print(" - {}: {}".format(f, color(Fore.GREEN, "SUCCESS"))) + print(f" - {f}: {color(Fore.GREEN, 'SUCCESS')}") else: - print(" - {}: {}".format(f, color(Fore.BOLD_RED, "FAILED"))) + print(f" - {f}: {color(Fore.BOLD_RED, 'FAILED')}") failed += 1 return failed diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 9cd2a045ff..60ac4303a7 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -231,17 +231,16 @@ def parse_multi_click_timing_str(value): parts = value.lower().split(" ") if len(parts) != 5: raise cv.Invalid( - "Multi click timing grammar consists of exactly 5 words, not {}" - "".format(len(parts)) + f"Multi click timing grammar consists of exactly 5 words, not {len(parts)}" ) try: state = cv.boolean(parts[0]) except cv.Invalid: # pylint: disable=raise-missing-from - raise cv.Invalid("First word must either be ON or OFF, not {}".format(parts[0])) + raise cv.Invalid(f"First word must either be ON or OFF, not {parts[0]}") if parts[1] != "for": - raise cv.Invalid("Second word must be 'for', got {}".format(parts[1])) + raise cv.Invalid(f"Second word must be 'for', got {parts[1]}") if parts[2] == "at": if parts[3] == "least": @@ -250,8 +249,7 @@ def parse_multi_click_timing_str(value): key = CONF_MAX_LENGTH else: raise cv.Invalid( - "Third word after at must either be 'least' or 'most', got {}" - "".format(parts[3]) + f"Third word after at must either be 'least' or 'most', got {parts[3]}" ) try: length = cv.positive_time_period_milliseconds(parts[4]) @@ -296,13 +294,11 @@ def validate_multi_click_timing(value): new_state = v_.get(CONF_STATE, not state) if new_state == state: raise cv.Invalid( - "Timings must have alternating state. Indices {} and {} have " - "the same state {}".format(i, i + 1, state) + f"Timings must have alternating state. Indices {i} and {i + 1} have the same state {state}" ) if max_length is not None and max_length < min_length: raise cv.Invalid( - "Max length ({}) must be larger than min length ({})." - "".format(max_length, min_length) + f"Max length ({max_length}) must be larger than min length ({min_length})." ) state = new_state diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index b7bf27e79a..3f59ad52cf 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -16,8 +16,7 @@ def validate_pin_number(value): valid_pins = [0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39] if value[CONF_NUMBER] not in valid_pins: raise cv.Invalid( - "Only pins {} support wakeup" - "".format(", ".join(str(x) for x in valid_pins)) + f"Only pins {', '.join(str(x) for x in valid_pins)} support wakeup" ) return value diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index 3e00692d3a..cd0cb4bed6 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -24,9 +24,7 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): uuid = config[CONF_UUID].hex - uuid_arr = [ - cg.RawExpression("0x{}".format(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) await cg.register_component(var, config) cg.add(var.set_major(config[CONF_MAJOR])) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index fec0f6dcfb..162a4dee89 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -51,8 +51,7 @@ def validate_scan_parameters(config): if window > interval: raise cv.Invalid( - "Scan window ({}) needs to be smaller than scan interval ({})" - "".format(window, interval) + f"Scan window ({window}) needs to be smaller than scan interval ({interval})" ) if interval.total_milliseconds * 3 > duration.total_milliseconds: @@ -97,9 +96,7 @@ def bt_uuid(value): ) return value raise cv.Invalid( - "Service UUID must be in 16 bit '{}', 32 bit '{}', or 128 bit '{}' format".format( - bt_uuid16_format, bt_uuid32_format, bt_uuid128_format - ) + f"Service UUID must be in 16 bit '{bt_uuid16_format}', 32 bit '{bt_uuid32_format}', or 128 bit '{bt_uuid128_format}' format" ) @@ -112,9 +109,7 @@ def as_hex_array(value): cpp_array = [ f"0x{part}" for part in [value[i : i + 2] for i in range(0, len(value), 2)] ] - return cg.RawExpression( - "(uint8_t*)(const uint8_t[16]){{{}}}".format(",".join(cpp_array)) - ) + return cg.RawExpression(f"(uint8_t*)(const uint8_t[16]){{{','.join(cpp_array)}}}") def as_reversed_hex_array(value): @@ -123,7 +118,7 @@ def as_reversed_hex_array(value): f"0x{part}" for part in [value[i : i + 2] for i in range(0, len(value), 2)] ] return cg.RawExpression( - "(uint8_t*)(const uint8_t[16]){{{}}}".format(",".join(reversed(cpp_array))) + f"(uint8_t*)(const uint8_t[16]){{{','.join(reversed(cpp_array))}}}" ) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 16a7d8a612..e47a6f38af 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -61,8 +61,7 @@ def validate_pillow_installed(value): def validate_truetype_file(value): if value.endswith(".zip"): # for Google Fonts downloads raise cv.Invalid( - "Please unzip the font archive '{}' first and then use the .ttf files " - "inside.".format(value) + f"Please unzip the font archive '{value}' first and then use the .ttf files inside." ) if not value.endswith(".ttf"): raise cv.Invalid( @@ -131,7 +130,7 @@ async def to_code(config): ("a_char", glyph), ( "data", - cg.RawExpression(str(prog_arr) + " + " + str(glyph_args[glyph][0])), + cg.RawExpression(f"{str(prog_arr)} + {str(glyph_args[glyph][0])}"), ), ("offset_x", glyph_args[glyph][1]), ("offset_y", glyph_args[glyph][2]), diff --git a/esphome/components/lcd_gpio/display.py b/esphome/components/lcd_gpio/display.py index 6b0a2f69de..9fb635eafa 100644 --- a/esphome/components/lcd_gpio/display.py +++ b/esphome/components/lcd_gpio/display.py @@ -20,8 +20,7 @@ GPIOLCDDisplay = lcd_gpio_ns.class_("GPIOLCDDisplay", lcd_base.LCDDisplay) def validate_pin_length(value): if len(value) != 4 and len(value) != 8: raise cv.Invalid( - "LCD Displays can either operate in 4-pin or 8-pin mode," - "not {}-pin mode".format(len(value)) + f"LCD Displays can either operate in 4-pin or 8-pin mode,not {len(value)}-pin mode" ) return value diff --git a/esphome/components/ledc/output.py b/esphome/components/ledc/output.py index 83b1c6f096..0f5f186ff5 100644 --- a/esphome/components/ledc/output.py +++ b/esphome/components/ledc/output.py @@ -28,13 +28,11 @@ def validate_frequency(value): max_freq = calc_max_frequency(1) if value < min_freq: raise cv.Invalid( - "This frequency setting is not possible, please choose a higher " - "frequency (at least {}Hz)".format(int(min_freq)) + f"This frequency setting is not possible, please choose a higher frequency (at least {int(min_freq)}Hz)" ) if value > max_freq: raise cv.Invalid( - "This frequency setting is not possible, please choose a lower " - "frequency (at most {}Hz)".format(int(max_freq)) + f"This frequency setting is not possible, please choose a lower frequency (at most {int(max_freq)}Hz)" ) return value diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index be558a8140..4b2209c833 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -490,8 +490,7 @@ def validate_effects(allowed_effects): if key not in allowed_effects: errors.append( cv.Invalid( - "The effect '{}' is not allowed for this " - "light type".format(key), + f"The effect '{key}' is not allowed for this light type", [i], ) ) @@ -500,8 +499,7 @@ def validate_effects(allowed_effects): if name in names: errors.append( cv.Invalid( - "Found the effect name '{}' twice. All effects must have " - "unique names".format(name), + f"Found the effect name '{name}' twice. All effects must have unique names", [i], ) ) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 55178941ec..b821e8c5d8 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -86,8 +86,7 @@ def validate_local_no_higher_than_global(value): for tag, level in value.get(CONF_LOGS, {}).items(): if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level): raise EsphomeError( - "The local log level {} for {} must be less severe than the " - "global log level {}.".format(level, tag, global_level) + f"The local log level {level} for {tag} must be less severe than the global log level {global_level}." ) return value @@ -145,7 +144,7 @@ async def to_code(config): level = config[CONF_LEVEL] cg.add_define("USE_LOGGER") this_severity = LOG_LEVEL_SEVERITY.index(level) - cg.add_build_flag("-DESPHOME_LOG_LEVEL={}".format(LOG_LEVELS[level])) + cg.add_build_flag(f"-DESPHOME_LOG_LEVEL={LOG_LEVELS[level]}") verbose_severity = LOG_LEVEL_SEVERITY.index("VERBOSE") very_verbose_severity = LOG_LEVEL_SEVERITY.index("VERY_VERBOSE") @@ -220,8 +219,7 @@ def validate_printf(value): matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X) if len(matches) != len(value[CONF_ARGS]): raise cv.Invalid( - "Found {} printf-patterns ({}), but {} args were given!" - "".format(len(matches), ", ".join(matches), len(value[CONF_ARGS])) + f"Found {len(matches)} printf-patterns ({', '.join(matches)}), but {len(value[CONF_ARGS])} args were given!" ) return value diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 19f78641df..73ee50ee65 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -266,8 +266,7 @@ async def to_code(config): if CONF_SSL_FINGERPRINTS in config: for fingerprint in config[CONF_SSL_FINGERPRINTS]: arr = [ - cg.RawExpression("0x{}".format(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") @@ -353,9 +352,7 @@ def get_default_topic_for(data, component_type, name, suffix): sanitized_name = "".join( x for x in name.lower().replace(" ", "_") if x in allowlist ) - return "{}/{}/{}/{}".format( - data.topic_prefix, component_type, sanitized_name, suffix - ) + return f"{data.topic_prefix}/{component_type}/{sanitized_name}/{suffix}" async def register_mqtt_component(var, config): diff --git a/esphome/components/neopixelbus/light.py b/esphome/components/neopixelbus/light.py index 5eee5210f9..a86b4e4588 100644 --- a/esphome/components/neopixelbus/light.py +++ b/esphome/components/neopixelbus/light.py @@ -40,7 +40,7 @@ def validate_type(value): raise cv.Invalid("Must have B in type") rest = set(value) - set("RGBW") if rest: - raise cv.Invalid("Type has invalid color: {}".format(", ".join(rest))) + raise cv.Invalid(f"Type has invalid color: {', '.join(rest)}") if len(set(value)) != len(value): raise cv.Invalid("Type has duplicate color!") return value @@ -95,9 +95,7 @@ def validate_method_pin(value): for opt in (CONF_PIN, CONF_CLOCK_PIN, CONF_DATA_PIN): if opt in value and value[opt] not in pins_: raise cv.Invalid( - "Method {} only supports pin(s) {}".format( - method, ", ".join(f"GPIO{x}" for x in pins_) - ), + f"Method {method} only supports pin(s) {', '.join(f'GPIO{x}' for x in pins_)}", path=[CONF_METHOD], ) return value @@ -139,7 +137,7 @@ def format_method(config): if config[CONF_INVERT]: if method == "ESP8266_DMA": - variant = "Inverted" + variant + variant = f"Inverted{variant}" else: variant += "Inverted" diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index ce567bc3f1..75694ee4b2 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -30,16 +30,14 @@ CONF_FONT_ID = "font_id" def NextionName(value): - valid_chars = ascii_letters + digits + "." + valid_chars = f"{ascii_letters + digits}." if not isinstance(value, str) or len(value) > 29: raise cv.Invalid("Must be a string less than 29 characters") for char in value: if char not in valid_chars: raise cv.Invalid( - "Must only consist of upper/lowercase characters, numbers and the period '.'. The character '{}' cannot be used.".format( - char - ) + f"Must only consist of upper/lowercase characters, numbers and the period '.'. The character '{char}' cannot be used." ) return value diff --git a/esphome/components/ntc/sensor.py b/esphome/components/ntc/sensor.py index bf819ffd16..660208635c 100644 --- a/esphome/components/ntc/sensor.py +++ b/esphome/components/ntc/sensor.py @@ -105,9 +105,7 @@ def process_calibration(value): a, b, c = calc_steinhart_hart(value) else: raise cv.Invalid( - "Calibration parameter accepts either a list for steinhart-hart " - "calibration, or mapping for b-constant calibration, " - "not {}".format(type(value)) + f"Calibration parameter accepts either a list for steinhart-hart calibration, or mapping for b-constant calibration, not {type(value)}" ) return { diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index 330ffc2bf2..df0f0de13d 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -151,8 +151,7 @@ def do_packages_pass(config: dict): packages = CONFIG_SCHEMA(packages) if not isinstance(packages, dict): raise cv.Invalid( - "Packages must be a key to value mapping, got {} instead" - "".format(type(packages)) + f"Packages must be a key to value mapping, got {type(packages)} instead" ) for package_name, package_config in packages.items(): diff --git a/esphome/components/partition/light.py b/esphome/components/partition/light.py index 5ded6b906c..06bee2143e 100644 --- a/esphome/components/partition/light.py +++ b/esphome/components/partition/light.py @@ -20,8 +20,7 @@ PartitionLightOutput = partitions_ns.class_( def validate_from_to(value): if value[CONF_FROM] > value[CONF_TO]: raise cv.Invalid( - "From ({}) must not be larger than to ({})" - "".format(value[CONF_FROM], value[CONF_TO]) + f"From ({value[CONF_FROM]}) must not be larger than to ({value[CONF_TO]})" ) return value diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index 8b9e5c9af2..350117a235 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -63,9 +63,7 @@ SENSORS_TO_TYPE = { def validate_pmsx003_sensors(value): for key, types in SENSORS_TO_TYPE.items(): if key in value and value[CONF_TYPE] not in types: - raise cv.Invalid( - "{} does not have {} sensor!".format(value[CONF_TYPE], key) - ) + raise cv.Invalid(f"{value[CONF_TYPE]} does not have {key} sensor!") return value diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index d76dc6bc34..537ae2283c 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -491,8 +491,7 @@ def validate_raw_alternating(value): if i != 0: if this_negative == last_negative: raise cv.Invalid( - "Values must alternate between being positive and negative, " - "please see index {} and {}".format(i, i + 1), + f"Values must alternate between being positive and negative, please see index {i} and {i + 1}", [i], ) last_negative = this_negative @@ -619,13 +618,11 @@ def validate_rc_switch_code(value): for c in value: if c not in ("0", "1"): raise cv.Invalid( - "Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed" - "".format(c) + f"Invalid RCSwitch code character '{c}'. Only '0' and '1' are allowed" ) if len(value) > 64: raise cv.Invalid( - "Maximum length for RCSwitch codes is 64, code '{}' has length {}" - "".format(value, len(value)) + f"Maximum length for RCSwitch codes is 64, code '{value}' has length {len(value)}" ) if not value: raise cv.Invalid("RCSwitch code must not be empty") @@ -638,14 +635,11 @@ def validate_rc_switch_raw_code(value): for c in value: if c not in ("0", "1", "x"): raise cv.Invalid( - "Invalid RCSwitch raw code character '{}'.Only '0', '1' and 'x' are allowed".format( - c - ) + f"Invalid RCSwitch raw code character '{c}'.Only '0', '1' and 'x' are allowed" ) if len(value) > 64: raise cv.Invalid( - "Maximum length for RCSwitch raw codes is 64, code '{}' has length {}" - "".format(value, len(value)) + f"Maximum length for RCSwitch raw codes is 64, code '{value}' has length {len(value)}" ) if not value: raise cv.Invalid("RCSwitch raw code must not be empty") diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index 311e63a7ba..e82b9d5f13 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -49,8 +49,7 @@ def validate_min_max_value(config): max_val = config[CONF_MAX_VALUE] if min_val >= max_val: raise cv.Invalid( - "Max value {} must be smaller than min value {}" - "".format(max_val, min_val) + f"Max value {max_val} must be smaller than min value {min_val}" ) return config diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index fd278be51e..ce4aafb3b0 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -109,8 +109,7 @@ def validate_send_first_at(value): send_every = value[CONF_SEND_EVERY] if send_first_at is not None and send_first_at > send_every: raise cv.Invalid( - "send_first_at must be smaller than or equal to send_every! {} <= {}" - "".format(send_first_at, send_every) + f"send_first_at must be smaller than or equal to send_every! {send_first_at} <= {send_every}" ) return value @@ -459,8 +458,7 @@ CONF_DEGREE = "degree" def validate_calibrate_polynomial(config): if config[CONF_DEGREE] >= len(config[CONF_DATAPOINTS]): raise cv.Invalid( - "Degree is too high! Maximum possible degree with given datapoints is " - "{}".format(len(config[CONF_DATAPOINTS]) - 1), + f"Degree is too high! Maximum possible degree with given datapoints is {len(config[CONF_DATAPOINTS]) - 1}", [CONF_DEGREE], ) return config diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index e7a5e24ee6..0cef417c15 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -25,8 +25,7 @@ def validate_substitution_key(value): for char in value: if char not in VALID_SUBSTITUTIONS_CHARACTERS: raise cv.Invalid( - "Substitution must only consist of upper/lowercase characters, the underscore " - "and numbers. The character '{}' cannot be used".format(char) + f"Substitution must only consist of upper/lowercase characters, the underscore and numbers. The character '{char}' cannot be used" ) return value @@ -42,6 +41,7 @@ async def to_code(config): pass +# pylint: disable=consider-using-f-string VARIABLE_PROG = re.compile( "\\$([{0}]+|\\{{[{0}]*\\}})".format(VALID_SUBSTITUTIONS_CHARACTERS) ) @@ -133,8 +133,7 @@ def do_substitution_pass(config, command_line_substitutions): with cv.prepend_path("substitutions"): if not isinstance(substitutions, dict): raise cv.Invalid( - "Substitutions must be a key to value mapping, got {}" - "".format(type(substitutions)) + f"Substitutions must be a key to value mapping, got {type(substitutions)}" ) replace_keys = [] diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 4872c89f88..d548575d72 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -67,9 +67,7 @@ def _week_of_month(dt): def _tz_dst_str(dt): td = datetime.timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second) - return "M{}.{}.{}/{}".format( - dt.month, _week_of_month(dt), dt.isoweekday() % 7, _tz_timedelta(td) - ) + return f"M{dt.month}.{_week_of_month(dt)}.{dt.isoweekday() % 7}/{_tz_timedelta(td)}" def _safe_tzname(tz, dt): @@ -88,7 +86,7 @@ def _non_dst_tz(tz, dt): _LOGGER.info( "Detected timezone '%s' with UTC offset %s", tzname, _tz_timedelta(utcoffset) ) - tzbase = "{}{}".format(tzname, _tz_timedelta(-1 * utcoffset)) + tzbase = f"{tzname}{_tz_timedelta(-1 * utcoffset)}" return tzbase @@ -129,14 +127,9 @@ def convert_tz(pytz_obj): dst_ends_utc = transition_times[idx2] dst_ends_local = dst_ends_utc + utcoffset_on - tzbase = "{}{}".format(tzname_off, _tz_timedelta(-1 * utcoffset_off)) + tzbase = f"{tzname_off}{_tz_timedelta(-1 * utcoffset_off)}" - tzext = "{}{},{},{}".format( - tzname_on, - _tz_timedelta(-1 * utcoffset_on), - _tz_dst_str(dst_begins_local), - _tz_dst_str(dst_ends_local), - ) + tzext = f"{tzname_on}{_tz_timedelta(-1 * utcoffset_on)},{_tz_dst_str(dst_begins_local)},{_tz_dst_str(dst_ends_local)}" _LOGGER.info( "Detected timezone '%s' with UTC offset %s and daylight saving time from " "%s to %s", @@ -176,9 +169,7 @@ def _parse_cron_part(part, min_value, max_value, special_mapping): data = part.split("/") if len(data) > 2: raise cv.Invalid( - "Can't have more than two '/' in one time expression, got {}".format( - part - ) + f"Can't have more than two '/' in one time expression, got {part}" ) offset, repeat = data offset_n = 0 @@ -194,18 +185,14 @@ def _parse_cron_part(part, min_value, max_value, special_mapping): except ValueError: # pylint: disable=raise-missing-from raise cv.Invalid( - "Repeat for '/' time expression must be an integer, got {}".format( - repeat - ) + f"Repeat for '/' time expression must be an integer, got {repeat}" ) return set(range(offset_n, max_value + 1, repeat_n)) if "-" in part: data = part.split("-") if len(data) > 2: raise cv.Invalid( - "Can't have more than two '-' in range time expression '{}'".format( - part - ) + f"Can't have more than two '-' in range time expression '{part}'" ) begin, end = data begin_n = _parse_cron_int( @@ -233,13 +220,11 @@ def cron_expression_validator(name, min_value, max_value, special_mapping=None): for v in value: if not isinstance(v, int): raise cv.Invalid( - "Expected integer for {} '{}', got {}".format(v, name, type(v)) + f"Expected integer for {v} '{name}', got {type(v)}" ) if v < min_value or v > max_value: raise cv.Invalid( - "{} {} is out of range (min={} max={}).".format( - name, v, min_value, max_value - ) + f"{name} {v} is out of range (min={min_value} max={max_value})." ) return list(sorted(value)) value = cv.string(value) @@ -295,8 +280,7 @@ def validate_cron_raw(value): value = value.split(" ") if len(value) != 6: raise cv.Invalid( - "Cron expression must consist of exactly 6 space-separated parts, " - "not {}".format(len(value)) + f"Cron expression must consist of exactly 6 space-separated parts, not {len(value)}" ) seconds, minutes, hours, days_of_month, months, days_of_week = value return { diff --git a/esphome/components/wifi/wpa2_eap.py b/esphome/components/wifi/wpa2_eap.py index 071737ccd7..3cb60e6175 100644 --- a/esphome/components/wifi/wpa2_eap.py +++ b/esphome/components/wifi/wpa2_eap.py @@ -57,6 +57,7 @@ def wrapped_load_pem_private_key(value, password): def read_relative_config_path(value): + # pylint: disable=unspecified-encoding return Path(CORE.relative_config_path(value)).read_text() diff --git a/esphome/config.py b/esphome/config.py index de261f7eba..e49293e6b2 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -42,7 +42,7 @@ def iter_components(config): yield domain, component, conf if component.is_platform_component: for p_config in conf: - p_name = "{}.{}".format(domain, p_config[CONF_PLATFORM]) + p_name = f"{domain}.{p_config[CONF_PLATFORM]}" platform = get_platform(domain, p_config[CONF_PLATFORM]) yield p_name, platform, p_config @@ -238,10 +238,7 @@ def do_id_pass(result): # type: (Config) -> None # No declared ID with this name import difflib - error = ( - "Couldn't find ID '{}'. Please check you have defined " - "an ID with that name in your configuration.".format(id.id) - ) + error = f"Couldn't find ID '{id.id}'. Please check you have defined an ID with that name in your configuration." # Find candidates matches = difflib.get_close_matches( id.id, [v[0].id for v in result.declare_ids if v[0].is_manual] @@ -257,9 +254,7 @@ def do_id_pass(result): # type: (Config) -> None continue if not match.type.inherits_from(id.type): result.add_str_error( - "ID '{}' of type {} doesn't inherit from {}. Please " - "double check your ID is pointing to the correct value" - "".format(id.id, match.type, id.type), + f"ID '{id.id}' of type {match.type} doesn't inherit from {id.type}. Please double check your ID is pointing to the correct value", path, ) @@ -497,7 +492,7 @@ def validate_config(config, command_line_substitutions): for dependency in comp.dependencies: if dependency not in config: result.add_str_error( - "Component {} requires component {}" "".format(domain, dependency), + f"Component {domain} requires component {dependency}", path, ) success = False @@ -508,8 +503,7 @@ def validate_config(config, command_line_substitutions): for conflict in comp.conflicts_with: if conflict in config: result.add_str_error( - "Component {} cannot be used together with component {}" - "".format(domain, conflict), + f"Component {domain} cannot be used together with component {conflict}", path, ) success = False @@ -518,7 +512,7 @@ def validate_config(config, command_line_substitutions): if CORE.esp_platform not in comp.esp_platforms: result.add_str_error( - "Component {} doesn't support {}.".format(domain, CORE.esp_platform), + f"Component {domain} doesn't support {CORE.esp_platform}.", path, ) continue @@ -529,8 +523,7 @@ def validate_config(config, command_line_substitutions): and not isinstance(conf, core.AutoLoad) ): result.add_str_error( - "Component {} cannot be loaded via YAML " - "(no CONFIG_SCHEMA).".format(domain), + f"Component {domain} cannot be loaded via YAML (no CONFIG_SCHEMA).", path, ) continue @@ -540,8 +533,7 @@ def validate_config(config, command_line_substitutions): result[domain] = conf = [conf] if not isinstance(comp.multi_conf, bool) and len(conf) > comp.multi_conf: result.add_str_error( - "Component {} supports a maximum of {} " - "entries ({} found).".format(domain, comp.multi_conf, len(conf)), + f"Component {domain} supports a maximum of {comp.multi_conf} entries ({len(conf)} found).", path, ) continue @@ -636,18 +628,14 @@ def _format_vol_invalid(ex, config): if isinstance(ex, ExtraKeysInvalid): if ex.candidates: - message += "[{}] is an invalid option for [{}]. Did you mean {}?".format( - ex.path[-1], paren, ", ".join(f"[{x}]" for x in ex.candidates) - ) + message += f"[{ex.path[-1]}] is an invalid option for [{paren}]. Did you mean {', '.join(f'[{x}]' for x in ex.candidates)}?" else: - message += "[{}] is an invalid option for [{}]. Please check the indentation.".format( - ex.path[-1], paren - ) + message += f"[{ex.path[-1]}] is an invalid option for [{paren}]. Please check the indentation." elif "extra keys not allowed" in str(ex): - message += "[{}] is an invalid option for [{}].".format(ex.path[-1], paren) + message += f"[{ex.path[-1]}] is an invalid option for [{paren}]." elif isinstance(ex, vol.RequiredFieldInvalid): if ex.msg == "required key not provided": - message += "'{}' is a required option for [{}].".format(ex.path[-1], paren) + message += f"'{ex.path[-1]}' is a required option for [{paren}]." else: # Required has set a custom error message message += ex.msg @@ -700,7 +688,7 @@ def line_info(config, path, highlight=True): obj = config.get_deepest_document_range_for_path(path) if obj: mark = obj.start_mark - source = "[source {}:{}]".format(mark.document, mark.line + 1) + source = f"[source {mark.document}:{mark.line + 1}]" return color(Fore.CYAN, source) return "None" @@ -724,9 +712,7 @@ def dump_dict(config, path, at_root=True): if at_root: error = config.get_error_for_path(path) if error is not None: - ret += ( - "\n" + color(Fore.BOLD_RED, _format_vol_invalid(error, config)) + "\n" - ) + ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n" if isinstance(conf, (list, tuple)): multiline = True @@ -738,11 +724,7 @@ def dump_dict(config, path, at_root=True): path_ = path + [i] error = config.get_error_for_path(path_) if error is not None: - ret += ( - "\n" - + color(Fore.BOLD_RED, _format_vol_invalid(error, config)) - + "\n" - ) + ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n" sep = "- " if config.is_in_error_path(path_): @@ -751,10 +733,10 @@ def dump_dict(config, path, at_root=True): msg = indent(msg) inf = line_info(config, path_, highlight=config.is_in_error_path(path_)) if inf is not None: - msg = inf + "\n" + msg + msg = f"{inf}\n{msg}" elif msg: msg = msg[2:] - ret += sep + msg + "\n" + ret += f"{sep + msg}\n" elif isinstance(conf, dict): multiline = True if not conf: @@ -765,11 +747,7 @@ def dump_dict(config, path, at_root=True): path_ = path + [k] error = config.get_error_for_path(path_) if error is not None: - ret += ( - "\n" - + color(Fore.BOLD_RED, _format_vol_invalid(error, config)) - + "\n" - ) + ret += f"\n{color(Fore.BOLD_RED, _format_vol_invalid(error, config))}\n" st = f"{k}: " if config.is_in_error_path(path_): @@ -778,30 +756,30 @@ def dump_dict(config, path, at_root=True): inf = line_info(config, path_, highlight=config.is_in_error_path(path_)) if m: - msg = "\n" + indent(msg) + msg = f"\n{indent(msg)}" if inf is not None: if m: - msg = " " + inf + msg + msg = f" {inf}{msg}" else: - msg = msg + " " + inf - ret += st + msg + "\n" + msg = f"{msg} {inf}" + ret += f"{st + msg}\n" elif isinstance(conf, str): if is_secret(conf): - conf = "!secret {}".format(is_secret(conf)) + conf = f"!secret {is_secret(conf)}" if not conf: conf += "''" if len(conf) > 80: - conf = "|-\n" + indent(conf) + conf = f"|-\n{indent(conf)}" error = config.get_error_for_path(path) col = Fore.BOLD_RED if error else Fore.KEEP ret += color(col, str(conf)) elif isinstance(conf, core.Lambda): if is_secret(conf): - conf = "!secret {}".format(is_secret(conf)) + conf = f"!secret {is_secret(conf)}" - conf = "!lambda |-\n" + indent(str(conf.value)) + conf = f"!lambda |-\n{indent(str(conf.value))}" error = config.get_error_for_path(path) col = Fore.BOLD_RED if error else Fore.KEEP ret += color(col, conf) @@ -860,7 +838,7 @@ def read_config(command_line_substitutions): errstr = color(Fore.BOLD_RED, f"{domain}:") errline = line_info(res, path) if errline: - errstr += " " + errline + errstr += f" {errline}" safe_print(errstr) safe_print(indent(dump_dict(res, path)[0])) return None diff --git a/esphome/config_validation.py b/esphome/config_validation.py index fb659c41ea..a864c65dc7 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -277,8 +277,7 @@ def string_strict(value): if isinstance(value, str): return value raise Invalid( - "Must be string, got {}. did you forget putting quotes " - "around the value?".format(type(value)) + f"Must be string, got {type(value)}. did you forget putting quotes around the value?" ) @@ -311,8 +310,7 @@ def boolean(value): if value in ("false", "no", "off", "disable"): return False raise Invalid( - "Expected boolean value, but cannot convert {} to a boolean. " - "Please use 'true' or 'false'".format(value) + f"Expected boolean value, but cannot convert {value} to a boolean. Please use 'true' or 'false'" ) @@ -358,8 +356,7 @@ def int_(value): if int(value) == value: return int(value) raise Invalid( - "This option only accepts integers with no fractional part. Please remove " - "the fractional part from {}".format(value) + f"This option only accepts integers with no fractional part. Please remove the fractional part from {value}" ) value = string_strict(value).lower() base = 10 @@ -424,20 +421,17 @@ def validate_id_name(value): raise Invalid( "Dashes are not supported in IDs, please use underscores instead." ) - valid_chars = ascii_letters + digits + "_" + valid_chars = f"{ascii_letters + digits}_" for char in value: if char not in valid_chars: raise Invalid( - "IDs must only consist of upper/lowercase characters, the underscore" - "character and numbers. The character '{}' cannot be used" - "".format(char) + f"IDs must only consist of upper/lowercase characters, the underscorecharacter and numbers. The character '{char}' cannot be used" ) if value in RESERVED_IDS: raise Invalid(f"ID '{value}' is reserved internally and cannot be used") if value in CORE.loaded_integrations: raise Invalid( - "ID '{}' conflicts with the name of an esphome integration, please use " - "another ID name.".format(value) + f"ID '{value}' conflicts with the name of an esphome integration, please use another ID name." ) return value @@ -525,7 +519,7 @@ def has_at_least_one_key(*keys): raise Invalid("expected dictionary") if not any(k in keys for k in obj): - raise Invalid("Must contain at least one of {}.".format(", ".join(keys))) + raise Invalid(f"Must contain at least one of {', '.join(keys)}.") return obj return validate @@ -540,9 +534,9 @@ def has_exactly_one_key(*keys): number = sum(k in keys for k in obj) if number > 1: - raise Invalid("Cannot specify more than one of {}.".format(", ".join(keys))) + raise Invalid(f"Cannot specify more than one of {', '.join(keys)}.") if number < 1: - raise Invalid("Must contain exactly one of {}.".format(", ".join(keys))) + raise Invalid(f"Must contain exactly one of {', '.join(keys)}.") return obj return validate @@ -557,7 +551,7 @@ def has_at_most_one_key(*keys): number = sum(k in keys for k in obj) if number > 1: - raise Invalid("Cannot specify more than one of {}.".format(", ".join(keys))) + raise Invalid(f"Cannot specify more than one of {', '.join(keys)}.") return obj return validate @@ -572,9 +566,7 @@ def has_none_or_all_keys(*keys): number = sum(k in keys for k in obj) if number != 0 and number != len(keys): - raise Invalid( - "Must specify either none or all of {}.".format(", ".join(keys)) - ) + raise Invalid(f"Must specify either none or all of {', '.join(keys)}.") return obj return validate @@ -632,8 +624,7 @@ def time_period_str_unit(value): if isinstance(value, int): raise Invalid( - "Don't know what '{0}' means as it has no time *unit*! Did you mean " - "'{0}s'?".format(value) + f"Don't know what '{value}' means as it has no time *unit*! Did you mean '{value}s'?" ) if isinstance(value, TimePeriod): value = str(value) @@ -659,7 +650,7 @@ def time_period_str_unit(value): match = re.match(r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*)$", value) if match is None: - raise Invalid("Expected time period with unit, " "got {}".format(value)) + raise Invalid(f"Expected time period with unit, got {value}") kwarg = unit_to_kwarg[one_of(*unit_to_kwarg)(match.group(2))] return TimePeriod(**{kwarg: float(match.group(1))}) @@ -796,7 +787,7 @@ METRIC_SUFFIXES = { def float_with_unit(quantity, regex_suffix, optional_unit=False): pattern = re.compile( - r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*?)" + regex_suffix + r"$", re.UNICODE + f"^([-+]?[0-9]*\\.?[0-9]*)\\s*(\\w*?){regex_suffix}$", re.UNICODE ) def validator(value): @@ -812,7 +803,7 @@ def float_with_unit(quantity, regex_suffix, optional_unit=False): mantissa = float(match.group(1)) if match.group(2) not in METRIC_SUFFIXES: - raise Invalid("Invalid {} suffix {}".format(quantity, match.group(2))) + raise Invalid(f"Invalid {quantity} suffix {match.group(2)}") multiplier = METRIC_SUFFIXES[match.group(2)] return mantissa * multiplier @@ -879,12 +870,11 @@ def validate_bytes(value): mantissa = int(match.group(1)) if match.group(2) not in METRIC_SUFFIXES: - raise Invalid("Invalid metric suffix {}".format(match.group(2))) + raise Invalid(f"Invalid metric suffix {match.group(2)}") multiplier = METRIC_SUFFIXES[match.group(2)] if multiplier < 1: raise Invalid( - "Only suffixes with positive exponents are supported. " - "Got {}".format(match.group(2)) + f"Only suffixes with positive exponents are supported. Got {match.group(2)}" ) return int(mantissa * multiplier) @@ -1184,10 +1174,8 @@ def one_of(*values, **kwargs): option = str(value) matches = difflib.get_close_matches(option, options_) if matches: - raise Invalid( - "Unknown value '{}', did you mean {}?" - "".format(value, ", ".join(f"'{x}'" for x in matches)) - ) + matches_str = ", ".join(f"'{x}'" for x in matches) + raise Invalid(f"Unknown value '{value}', did you mean {matches_str}?") raise Invalid(f"Unknown value '{value}', valid options are {options}.") return value @@ -1229,13 +1217,10 @@ def lambda_(value): entity_id_parts = re.split(LAMBDA_ENTITY_ID_PROG, value.value) if len(entity_id_parts) != 1: entity_ids = " ".join( - "'{}'".format(entity_id_parts[i]) for i in range(1, len(entity_id_parts), 2) + f"'{entity_id_parts[i]}'" for i in range(1, len(entity_id_parts), 2) ) raise Invalid( - "Lambda contains reference to entity-id-style ID {}. " - "The id() wrapper only works for ESPHome-internal types. For importing " - "states from Home Assistant use the 'homeassistant' sensor platforms." - "".format(entity_ids) + f"Lambda contains reference to entity-id-style ID {entity_ids}. The id() wrapper only works for ESPHome-internal types. For importing states from Home Assistant use the 'homeassistant' sensor platforms." ) return value @@ -1259,9 +1244,7 @@ def returning_lambda(value): def dimensions(value): if isinstance(value, list): if len(value) != 2: - raise Invalid( - "Dimensions must have a length of two, not {}".format(len(value)) - ) + raise Invalid(f"Dimensions must have a length of two, not {len(value)}") try: width, height = int(value[0]), int(value[1]) except ValueError: @@ -1301,19 +1284,16 @@ def directory(value): if data["content"]: return value raise Invalid( - "Could not find directory '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path)) + f"Could not find directory '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})." ) if not os.path.exists(path): raise Invalid( - "Could not find directory '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path)) + f"Could not find directory '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})." ) if not os.path.isdir(path): raise Invalid( - "Path '{}' is not a directory (full path: {})." - "".format(path, os.path.abspath(path)) + f"Path '{path}' is not a directory (full path: {os.path.abspath(path)})." ) return value @@ -1340,19 +1320,16 @@ def file_(value): if data["content"]: return value raise Invalid( - "Could not find file '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path)) + f"Could not find file '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})." ) if not os.path.exists(path): raise Invalid( - "Could not find file '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path)) + f"Could not find file '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})." ) if not os.path.isfile(path): raise Invalid( - "Path '{}' is not a file (full path: {})." - "".format(path, os.path.abspath(path)) + f"Path '{path}' is not a file (full path: {os.path.abspath(path)})." ) return value @@ -1405,7 +1382,7 @@ def typed_schema(schemas, **kwargs): value = value.copy() schema_option = value.pop(key, default_schema_option) if schema_option is None: - raise Invalid(key + " not specified!") + raise Invalid(f"{key} not specified!") key_v = key_validator(schema_option) value = schemas[key_v](value) value[key] = key_v @@ -1498,8 +1475,7 @@ def validate_registry_entry(name, registry): value = {value: {}} if not isinstance(value, dict): raise Invalid( - "{} must consist of key-value mapping! Got {}" - "".format(name.title(), value) + f"{name.title()} must consist of key-value mapping! Got {value}" ) key = next((x for x in value if x not in ignore_keys), None) if key is None: @@ -1509,9 +1485,8 @@ def validate_registry_entry(name, registry): key2 = next((x for x in value if x != key and x not in ignore_keys), None) if key2 is not None: raise Invalid( - "Cannot have two {0}s in one item. Key '{1}' overrides '{2}'! " - "Did you forget to indent the block inside the {0}?" - "".format(name, key, key2) + f"Cannot have two {name}s in one item. Key '{key}' overrides '{key2}'! " + f"Did you forget to indent the block inside the {key}?" ) if value[key] is None: diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index c45d0969e1..e89f64d14c 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -624,8 +624,7 @@ class EsphomeCore: expression = statement(expression) if not isinstance(expression, Statement): raise ValueError( - "Add '{}' must be expression or statement, not {}" - "".format(expression, type(expression)) + f"Add '{expression}' must be expression or statement, not {type(expression)}" ) self.main_statements.append(expression) @@ -639,8 +638,7 @@ class EsphomeCore: expression = statement(expression) if not isinstance(expression, Statement): raise ValueError( - "Add '{}' must be expression or statement, not {}" - "".format(expression, type(expression)) + f"Add '{expression}' must be expression or statement, not {type(expression)}" ) self.global_statements.append(expression) _LOGGER.debug("Adding global: %s", expression) @@ -649,8 +647,7 @@ class EsphomeCore: def add_library(self, library): if not isinstance(library, Library): raise ValueError( - "Library {} must be instance of Library, not {}" - "".format(library, type(library)) + f"Library {library} must be instance of Library, not {type(library)}" ) for other in self.libraries[:]: if other.name != library.name or other.name is None or library.name is None: @@ -660,9 +657,8 @@ class EsphomeCore: # Other is using a/the same repository, takes precendence break raise ValueError( - "Adding named Library with repository failed! Libraries {} and {} " + f"Adding named Library with repository failed! Libraries {library} and {other} " "requested with conflicting repositories!" - "".format(library, other) ) if library.repository is not None: @@ -681,9 +677,8 @@ class EsphomeCore: break raise ValueError( - "Version pinning failed! Libraries {} and {} " + f"Version pinning failed! Libraries {library} and {other} " "requested with conflicting versions!" - "".format(library, other) ) else: _LOGGER.debug("Adding library: %s", library) @@ -702,8 +697,7 @@ class EsphomeCore: pass else: raise ValueError( - "Define {} must be string or Define, not {}" - "".format(define, type(define)) + f"Define {define} must be string or Define, not {type(define)}" ) self.defines.add(define) _LOGGER.debug("Adding define: %s", define) diff --git a/esphome/core/config.py b/esphome/core/config.py index 45b8809f1e..222a775ee6 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -61,9 +61,7 @@ def validate_board(value: str): if value not in boardlist: raise cv.Invalid( - "Could not find board '{}'. Valid boards are {}".format( - value, ", ".join(sorted(boardlist)) - ) + f"Could not find board '{value}'. Valid boards are {', '.join(sorted(boardlist))}" ) return value @@ -102,9 +100,7 @@ def validate_arduino_version(value): and value_ not in PLATFORMIO_ESP8266_LUT ): raise cv.Invalid( - "Unfortunately the arduino framework version '{}' is unsupported " - "at this time. You can override this by manually using " - "espressif8266@".format(value) + f"Unfortunately the arduino framework version '{value}' is unsupported at this time. You can override this by manually using espressif8266@" ) if value_ in PLATFORMIO_ESP8266_LUT: return PLATFORMIO_ESP8266_LUT[value_] @@ -115,9 +111,7 @@ def validate_arduino_version(value): and value_ not in PLATFORMIO_ESP32_LUT ): raise cv.Invalid( - "Unfortunately the arduino framework version '{}' is unsupported " - "at this time. You can override this by manually using " - "espressif32@".format(value) + f"Unfortunately the arduino framework version '{value}' is unsupported at this time. You can override this by manually using espressif32@" ) if value_ in PLATFORMIO_ESP32_LUT: return PLATFORMIO_ESP32_LUT[value_] @@ -141,8 +135,7 @@ def valid_include(value): _, ext = os.path.splitext(value) if ext not in VALID_INCLUDE_EXTS: raise cv.Invalid( - "Include has invalid file extension {} - valid extensions are {}" - "".format(ext, ", ".join(VALID_INCLUDE_EXTS)) + f"Include has invalid file extension {ext} - valid extensions are {', '.join(VALID_INCLUDE_EXTS)}" ) return value diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index eda378e5eb..0442e2633b 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -182,7 +182,7 @@ class ArrayInitializer(Expression): cpp += f" {arg},\n" cpp += "}" else: - cpp = "{" + ", ".join(str(arg) for arg in self.args) + "}" + cpp = f"{{{', '.join(str(arg) for arg in self.args)}}}" return cpp @@ -348,13 +348,11 @@ def safe_exp(obj: SafeExpType) -> Expression: return float_ if isinstance(obj, ID): raise ValueError( - "Object {} is an ID. Did you forget to register the variable?" - "".format(obj) + f"Object {obj} is an ID. Did you forget to register the variable?" ) if inspect.isgenerator(obj): raise ValueError( - "Object {} is a coroutine. Did you forget to await the expression with " - "'await'?".format(obj) + f"Object {obj} is a coroutine. Did you forget to await the expression with 'await'?" ) raise ValueError("Object is not an expression", obj) @@ -703,7 +701,7 @@ class MockObj(Expression): return str(self.base) def __repr__(self): - return "MockObj<{}>".format(str(self.base)) + return f"MockObj<{str(self.base)}>" @property def _(self) -> "MockObj": @@ -761,7 +759,7 @@ class MockObjEnum(MockObj): self._is_class = kwargs.pop("is_class") base = kwargs.pop("base") if self._is_class: - base = base + "::" + self._enum + base = f"{base}::{self._enum}" kwargs["op"] = "::" kwargs["base"] = base MockObj.__init__(self, *args, **kwargs) diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 7912e4ae06..33fb485c2b 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -52,9 +52,7 @@ async def register_component(var, config): id_ = str(var.base) if id_ not in CORE.component_ids: raise ValueError( - "Component ID {} was not declared to inherit from Component, " - "or was registered twice. Please create a bug report with your " - "configuration.".format(id_) + f"Component ID {id_} was not declared to inherit from Component, or was registered twice. Please create a bug report with your configuration." ) CORE.component_ids.remove(id_) if CONF_SETUP_PRIORITY in config: diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index 97f9d60693..38689675af 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -368,7 +368,7 @@ class WizardRequestHandler(BaseHandler): if k in ("name", "platform", "board", "ssid", "psk", "password") } kwargs["ota_password"] = secrets.token_hex(16) - destination = settings.rel_path(kwargs["name"] + ".yaml") + destination = settings.rel_path(f"{kwargs['name']}.yaml") wizard.wizard_write(path=destination, **kwargs) self.set_status(200) self.finish() @@ -512,7 +512,7 @@ class MDNSStatusThread(threading.Thread): while not STOP_EVENT.is_set(): entries = _list_dashboard_entries() stat.request_query( - {entry.filename: entry.name + ".local." for entry in entries} + {entry.filename: f"{entry.name}.local." for entry in entries} ) PING_REQUEST.wait() @@ -795,27 +795,27 @@ def make_app(debug=get_bool_env(ENV_DEV)): rel = settings.relative_url app = tornado.web.Application( [ - (rel + "", MainRequestHandler), - (rel + "login", LoginHandler), - (rel + "logout", LogoutHandler), - (rel + "logs", EsphomeLogsHandler), - (rel + "upload", EsphomeUploadHandler), - (rel + "compile", EsphomeCompileHandler), - (rel + "validate", EsphomeValidateHandler), - (rel + "clean-mqtt", EsphomeCleanMqttHandler), - (rel + "clean", EsphomeCleanHandler), - (rel + "vscode", EsphomeVscodeHandler), - (rel + "ace", EsphomeAceEditorHandler), - (rel + "update-all", EsphomeUpdateAllHandler), - (rel + "info", InfoRequestHandler), - (rel + "edit", EditRequestHandler), - (rel + "download.bin", DownloadBinaryRequestHandler), - (rel + "serial-ports", SerialPortRequestHandler), - (rel + "ping", PingRequestHandler), - (rel + "delete", DeleteRequestHandler), - (rel + "undo-delete", UndoDeleteRequestHandler), - (rel + "wizard.html", WizardRequestHandler), - (rel + r"static/(.*)", StaticFileHandler, {"path": get_static_path()}), + (f"{rel}", MainRequestHandler), + (f"{rel}login", LoginHandler), + (f"{rel}logout", LogoutHandler), + (f"{rel}logs", EsphomeLogsHandler), + (f"{rel}upload", EsphomeUploadHandler), + (f"{rel}compile", EsphomeCompileHandler), + (f"{rel}validate", EsphomeValidateHandler), + (f"{rel}clean-mqtt", EsphomeCleanMqttHandler), + (f"{rel}clean", EsphomeCleanHandler), + (f"{rel}vscode", EsphomeVscodeHandler), + (f"{rel}ace", EsphomeAceEditorHandler), + (f"{rel}update-all", EsphomeUpdateAllHandler), + (f"{rel}info", InfoRequestHandler), + (f"{rel}edit", EditRequestHandler), + (f"{rel}download.bin", DownloadBinaryRequestHandler), + (f"{rel}serial-ports", SerialPortRequestHandler), + (f"{rel}ping", PingRequestHandler), + (f"{rel}delete", DeleteRequestHandler), + (f"{rel}undo-delete", UndoDeleteRequestHandler), + (f"{rel}wizard.html", WizardRequestHandler), + (f"{rel}static/(.*)", StaticFileHandler, {"path": get_static_path()}), ], **app_settings, ) diff --git a/esphome/espota2.py b/esphome/espota2.py index 351f6feda9..f8a2fab94c 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -52,9 +52,7 @@ class ProgressBar: return self.last_progress = new_progress block = int(round(bar_length * progress)) - text = "\rUploading: [{0}] {1}% {2}".format( - "=" * block + " " * (bar_length - block), new_progress, status - ) + text = f"\rUploading: [{'=' * block + ' ' * (bar_length - block)}] {new_progress}% {status}" sys.stderr.write(text) sys.stderr.flush() @@ -154,7 +152,7 @@ def check_error(data, expect): if not isinstance(expect, (list, tuple)): expect = [expect] if dat not in expect: - raise OTAError("Unexpected response from ESP: 0x{:02X}".format(data[0])) + raise OTAError(f"Unexpected response from ESP: 0x{data[0]:02X}") def send_check(sock, data, msg): diff --git a/esphome/helpers.py b/esphome/helpers.py index a1cb4367c5..3420b2cc12 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -54,7 +54,7 @@ def cpp_string_escape(string, encoding="utf-8"): result += f"\\{character:03o}" else: result += chr(character) - return '"' + result + '"' + return f'"{result}"' def run_system_command(*args): @@ -107,7 +107,7 @@ def _resolve_with_zeroconf(host): "host network mode?" ) from err try: - info = zc.resolve_host(host + ".") + info = zc.resolve_host(f"{host}.") except Exception as err: raise EsphomeError(f"Error resolving mDNS hostname: {err}") from err finally: @@ -136,9 +136,7 @@ def resolve_ip_address(host): return socket.gethostbyname(host) except OSError as err: errs.append(str(err)) - raise EsphomeError( - "Error resolving IP address: {}" "".format(", ".join(errs)) - ) from err + raise EsphomeError(f"Error resolving IP address: {', '.join(errs)}") from err def get_bool_env(var, default=False): diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 9be87b5c5d..07602e8ced 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -104,9 +104,9 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None): if CONF_LOG_TOPIC in conf: topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC] elif CONF_TOPIC_PREFIX in config[CONF_MQTT]: - topic = config[CONF_MQTT][CONF_TOPIC_PREFIX] + "/debug" + topic = f"{config[CONF_MQTT][CONF_TOPIC_PREFIX]}/debug" else: - topic = config[CONF_ESPHOME][CONF_NAME] + "/debug" + topic = f"{config[CONF_ESPHOME][CONF_NAME]}/debug" else: _LOGGER.error("MQTT isn't setup, can't start MQTT logs") return 1 @@ -158,9 +158,8 @@ def get_fingerprint(config): sha1 = hashlib.sha1(cert_der).hexdigest() - safe_print("SHA1 Fingerprint: " + color(Fore.CYAN, sha1)) + safe_print(f"SHA1 Fingerprint: {color(Fore.CYAN, sha1)}") safe_print( - "Copy the string above into mqtt.ssl_fingerprints section of {}" - "".format(CORE.config_path) + f"Copy the string above into mqtt.ssl_fingerprints section of {CORE.config_path}" ) return 0 diff --git a/esphome/pins.py b/esphome/pins.py index ff4ed9d9c1..c717424ff3 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -77,8 +77,7 @@ def validate_gpio_pin(value): raise cv.Invalid(f"ESP32-C3: Invalid pin number: {value}") if value in _ESP32C3_SDIO_PINS: raise cv.Invalid( - "This pin cannot be used on ESP32-C3s and is already used by " - "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) + f"This pin cannot be used on ESP32-C3s and is already used by the flash interface (function: {_ESP_SDIO_PINS[value]})" ) return value if CORE.is_esp32: @@ -86,8 +85,7 @@ def validate_gpio_pin(value): raise cv.Invalid(f"ESP32: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: raise cv.Invalid( - "This pin cannot be used on ESP32s and is already used by " - "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) + f"This pin cannot be used on ESP32s and is already used by the flash interface (function: {_ESP_SDIO_PINS[value]})" ) if 9 <= value <= 10: _LOGGER.warning( @@ -105,8 +103,7 @@ def validate_gpio_pin(value): raise cv.Invalid(f"ESP8266: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: raise cv.Invalid( - "This pin cannot be used on ESP8266s and is already used by " - "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) + f"This pin cannot be used on ESP8266s and is already used by the flash interface (function: {_ESP_SDIO_PINS[value]})" ) if 9 <= value <= 10: _LOGGER.warning( @@ -144,8 +141,7 @@ def output_pin(value): if CORE.is_esp32: if 34 <= value <= 39: raise cv.Invalid( - "ESP32: GPIO{} (34-39) can only be used as an " - "input pin.".format(value) + f"ESP32: GPIO{value} (34-39) can only be used as an input pin." ) return value if CORE.is_esp8266: @@ -278,8 +274,7 @@ def validate_has_interrupt(value): if CORE.is_esp8266: if value[CONF_NUMBER] >= 16: raise cv.Invalid( - "Pins GPIO16 and GPIO17 do not support interrupts and cannot be used " - "here, got {}".format(value[CONF_NUMBER]) + f"Pins GPIO16 and GPIO17 do not support interrupts and cannot be used here, got {value[CONF_NUMBER]}" ) return value diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 3d7e9a6d48..6506a44e88 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -39,7 +39,7 @@ def patch_structhash(): command.clean_build_dir = patched_clean_build_dir -IGNORE_LIB_WARNINGS = r"(?:" + "|".join(["Hash", "Update"]) + r")" +IGNORE_LIB_WARNINGS = f"(?:{'|'.join(['Hash', 'Update'])})" FILTER_PLATFORMIO_LINES = [ r"Verbose mode can be enabled via `-v, --verbose` option.*", r"CONFIGURATION: https://docs.platformio.org/.*", @@ -48,13 +48,9 @@ FILTER_PLATFORMIO_LINES = [ r"PACKAGES: .*", r"LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf.*", r"LDF Modes: Finder ~ chain, Compatibility ~ soft.*", - r"Looking for " + IGNORE_LIB_WARNINGS + r" library in registry", - r"Warning! Library `.*'" - + IGNORE_LIB_WARNINGS - + r".*` has not been found in PlatformIO Registry.", - r"You can ignore this message, if `.*" - + IGNORE_LIB_WARNINGS - + r".*` is a built-in library.*", + f"Looking for {IGNORE_LIB_WARNINGS} library in registry", + f"Warning! Library `.*'{IGNORE_LIB_WARNINGS}.*` has not been found in PlatformIO Registry.", + f"You can ignore this message, if `.*{IGNORE_LIB_WARNINGS}.*` is a built-in library.*", r"Scanning dependencies...", r"Found \d+ compatible libraries", r"Memory Usage -> http://bit.ly/pio-memory-usage", @@ -296,6 +292,6 @@ class IDEData: # Windows if cc_path.endswith(".exe"): - return cc_path[:-7] + "addr2line.exe" + return f"{cc_path[:-7]}addr2line.exe" - return cc_path[:-3] + "addr2line" + return f"{cc_path[:-3]}addr2line" diff --git a/esphome/storage_json.py b/esphome/storage_json.py index c0fbc6edf7..517bb508ba 100644 --- a/esphome/storage_json.py +++ b/esphome/storage_json.py @@ -94,7 +94,7 @@ class StorageJSON: } def to_json(self): - return json.dumps(self.as_dict(), indent=2) + "\n" + return f"{json.dumps(self.as_dict(), indent=2)}\n" def save(self, path): write_file_if_changed(path, self.to_json()) @@ -214,7 +214,7 @@ class EsphomeStorageJSON: self.last_update_check_str = new.strftime("%Y-%m-%dT%H:%M:%S") def to_json(self): # type: () -> dict - return json.dumps(self.as_dict(), indent=2) + "\n" + return f"{json.dumps(self.as_dict(), indent=2)}\n" def save(self, path): # type: (str) -> None write_file_if_changed(path, self.to_json()) diff --git a/esphome/wizard.py b/esphome/wizard.py index 3f989dd93d..abb17e3119 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -74,19 +74,20 @@ def wizard_file(**kwargs): # Configure API if "password" in kwargs: - config += ' password: "{0}"\n'.format(kwargs["password"]) + config += f" password: \"{kwargs['password']}\"\n" # Configure OTA config += "\nota:\n" if "ota_password" in kwargs: - config += ' password: "{0}"'.format(kwargs["ota_password"]) + config += f" password: \"{kwargs['ota_password']}\"" elif "password" in kwargs: - config += ' password: "{0}"'.format(kwargs["password"]) + config += f" password: \"{kwargs['password']}\"" # Configuring wifi config += "\n\nwifi:\n" if "ssid" in kwargs: + # pylint: disable=consider-using-f-string config += """ ssid: "{ssid}" password: "{psk}" """.format( @@ -99,6 +100,7 @@ def wizard_file(**kwargs): networks: """ + # pylint: disable=consider-using-f-string config += """ # Enable fallback hotspot (captive portal) in case wifi connection fails ap: @@ -126,7 +128,7 @@ def wizard_write(path, **kwargs): platform = kwargs["platform"] write_file(path, wizard_file(**kwargs)) - storage = StorageJSON.from_wizard(name, name + ".local", platform, board) + storage = StorageJSON.from_wizard(name, f"{name}.local", platform, board) storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path)) storage.save(storage_path) @@ -168,14 +170,12 @@ def strip_accents(value): def wizard(path): if not path.endswith(".yaml") and not path.endswith(".yml"): safe_print( - "Please make your configuration file {} have the extension .yaml or .yml" - "".format(color(Fore.CYAN, path)) + f"Please make your configuration file {color(Fore.CYAN, path)} have the extension .yaml or .yml" ) return 1 if os.path.exists(path): safe_print( - "Uh oh, it seems like {} already exists, please delete that file first " - "or chose another configuration file.".format(color(Fore.CYAN, path)) + f"Uh oh, it seems like {color(Fore.CYAN, path)} already exists, please delete that file first or chose another configuration file." ) return 2 safe_print("Hi there!") @@ -191,17 +191,13 @@ def wizard(path): sleep(3.0) safe_print() safe_print_step(1, CORE_BIG) - safe_print( - "First up, please choose a " + color(Fore.GREEN, "name") + " for your node." - ) + safe_print(f"First up, please choose a {color(Fore.GREEN, 'name')} for your node.") safe_print( "It should be a unique name that can be used to identify the device later." ) sleep(1) safe_print( - "For example, I like calling the node in my living room {}.".format( - color(Fore.BOLD_WHITE, "livingroom") - ) + f"For example, I like calling the node in my living room {color(Fore.BOLD_WHITE, 'livingroom')}." ) safe_print() sleep(1) @@ -222,13 +218,11 @@ def wizard(path): name = strip_accents(name).lower().replace(" ", "-") name = strip_accents(name).lower().replace("_", "-") name = "".join(c for c in name if c in ALLOWED_NAME_CHARS) - safe_print( - 'Shall I use "{}" as the name instead?'.format(color(Fore.CYAN, name)) - ) + safe_print(f'Shall I use "{color(Fore.CYAN, name)}" as the name instead?') sleep(0.5) name = default_input("(name [{}]): ", name) - safe_print('Great! Your node is now called "{}".'.format(color(Fore.CYAN, name))) + safe_print(f'Great! Your node is now called "{color(Fore.CYAN, name)}".') sleep(1) safe_print_step(2, ESP_BIG) safe_print( @@ -236,11 +230,7 @@ def wizard(path): "firmwares for it." ) safe_print( - "Are you using an " - + color(Fore.GREEN, "ESP32") - + " or " - + color(Fore.GREEN, "ESP8266") - + " platform? (Choose ESP8266 for Sonoff devices)" + f"Are you using an {color(Fore.GREEN, 'ESP32')} or {color(Fore.GREEN, 'ESP8266')} platform? (Choose ESP8266 for Sonoff devices)" ) while True: sleep(0.5) @@ -252,12 +242,9 @@ def wizard(path): break except vol.Invalid: safe_print( - "Unfortunately, I can't find an espressif microcontroller called " - '"{}". Please try again.'.format(platform) + f'Unfortunately, I can\'t find an espressif microcontroller called "{platform}". Please try again.' ) - safe_print( - "Thanks! You've chosen {} as your platform.".format(color(Fore.CYAN, platform)) - ) + safe_print(f"Thanks! You've chosen {color(Fore.CYAN, platform)} as your platform.") safe_print() sleep(1) @@ -270,24 +257,20 @@ def wizard(path): "http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards" ) - safe_print( - "Next, I need to know what " + color(Fore.GREEN, "board") + " you're using." - ) + safe_print(f"Next, I need to know what {color(Fore.GREEN, 'board')} you're using.") sleep(0.5) - safe_print( - "Please go to {} and choose a board.".format(color(Fore.GREEN, board_link)) - ) + safe_print(f"Please go to {color(Fore.GREEN, board_link)} and choose a board.") if platform == "ESP32": - safe_print("(Type " + color(Fore.GREEN, "esp01_1m") + " for Sonoff devices)") + safe_print(f"(Type {color(Fore.GREEN, 'esp01_1m')} for Sonoff devices)") safe_print() # Don't sleep because user needs to copy link if platform == "ESP32": - safe_print('For example "{}".'.format(color(Fore.BOLD_WHITE, "nodemcu-32s"))) + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcu-32s')}\".") boards = list(ESP32_BOARD_PINS.keys()) else: - safe_print('For example "{}".'.format(color(Fore.BOLD_WHITE, "nodemcuv2"))) + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'nodemcuv2')}\".") boards = list(ESP8266_BOARD_PINS.keys()) - safe_print("Options: {}".format(", ".join(sorted(boards)))) + safe_print(f"Options: {', '.join(sorted(boards))}") while True: board = input(color(Fore.BOLD_WHITE, "(board): ")) @@ -302,9 +285,7 @@ def wizard(path): sleep(0.25) safe_print() - safe_print( - "Way to go! You've chosen {} as your board.".format(color(Fore.CYAN, board)) - ) + safe_print(f"Way to go! You've chosen {color(Fore.CYAN, board)} as your board.") safe_print() sleep(1) @@ -313,12 +294,10 @@ def wizard(path): safe_print() sleep(1) safe_print( - "First, what's the " - + color(Fore.GREEN, "SSID") - + f" (the name) of the WiFi network {name} should connect to?" + f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?" ) sleep(1.5) - safe_print('For example "{}".'.format(color(Fore.BOLD_WHITE, "Abraham Linksys"))) + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") while True: ssid = input(color(Fore.BOLD_WHITE, "(ssid): ")) try: @@ -328,27 +307,23 @@ def wizard(path): safe_print( color( Fore.RED, - 'Unfortunately, "{}" doesn\'t seem to be a valid SSID. ' - "Please try again.".format(ssid), + f'Unfortunately, "{ssid}" doesn\'t seem to be a valid SSID. Please try again.', ) ) safe_print() sleep(1) safe_print( - 'Thank you very much! You\'ve just chosen "{}" as your SSID.' - "".format(color(Fore.CYAN, ssid)) + f'Thank you very much! You\'ve just chosen "{color(Fore.CYAN, ssid)}" as your SSID.' ) safe_print() sleep(0.75) safe_print( - "Now please state the " - + color(Fore.GREEN, "password") - + " of the WiFi network so that I can connect to it (Leave empty for no password)" + 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('For example "{}"'.format(color(Fore.BOLD_WHITE, "PASSWORD42"))) + safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") sleep(0.5) psk = input(color(Fore.BOLD_WHITE, "(PSK): ")) safe_print( @@ -362,8 +337,7 @@ def wizard(path): "(over the air) and integrates into Home Assistant with a native API." ) safe_print( - "This can be insecure if you do not trust the WiFi network. Do you want to set " - "a " + color(Fore.GREEN, "password") + " for connecting to this ESP?" + f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(Fore.GREEN, 'password')} for connecting to this ESP?" ) safe_print() sleep(0.25) diff --git a/esphome/writer.py b/esphome/writer.py index 09ed284173..19953916c7 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -96,7 +96,7 @@ def get_include_text(): includes = "\n".join(includes) if not includes: continue - include_text += includes + "\n" + include_text += f"{includes}\n" return include_text @@ -134,7 +134,7 @@ def migrate_src_version_0_to_1(): content, count = replace_file_content( content, r'#include "esphomelib/application.h"', - CPP_INCLUDE_BEGIN + "\n" + CPP_INCLUDE_END, + f"{CPP_INCLUDE_BEGIN}\n{CPP_INCLUDE_END}", ) if count == 0: _LOGGER.error( @@ -322,7 +322,7 @@ def write_platformio_ini(content): ) else: content_format = INI_BASE_FORMAT - full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + "\n" + content + full_file = f"{content_format[0] + INI_AUTO_GENERATE_BEGIN}\n{content}" full_file += INI_AUTO_GENERATE_END + content_format[1] write_file_if_changed(path, full_file) @@ -444,9 +444,9 @@ def write_cpp(code_s): global_s = '#include "esphome.h"\n' global_s += CORE.cpp_global_section - full_file = code_format[0] + CPP_INCLUDE_BEGIN + "\n" + global_s + CPP_INCLUDE_END + full_file = f"{code_format[0] + CPP_INCLUDE_BEGIN}\n{global_s}{CPP_INCLUDE_END}" full_file += ( - code_format[1] + CPP_AUTO_GENERATE_BEGIN + "\n" + code_s + CPP_AUTO_GENERATE_END + f"{code_format[1] + CPP_AUTO_GENERATE_BEGIN}\n{code_s}{CPP_AUTO_GENERATE_END}" ) full_file += code_format[2] write_file_if_changed(path, full_file) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index 10417e6de4..bdadbbd43a 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -183,9 +183,7 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors raise yaml.constructor.ConstructorError( "While constructing a mapping", node.start_mark, - "Expected a mapping for merging, but found {}".format( - type(item) - ), + f"Expected a mapping for merging, but found {type(item)}", value_node.start_mark, ) merge_pairs.extend(item.items()) @@ -193,8 +191,7 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors raise yaml.constructor.ConstructorError( "While constructing a mapping", node.start_mark, - "Expected a mapping or list of mappings for merging, " - "but found {}".format(type(value)), + f"Expected a mapping or list of mappings for merging, but found {type(value)}", value_node.start_mark, ) diff --git a/requirements_test.txt b/requirements_test.txt index bb735193f0..1d09bb6388 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -pylint==2.10.2 +pylint==2.11.1 flake8==3.9.2 black==21.9b0 pexpect==4.8.0