Various string cleanups (#30435)

* Remove some unnecessary string concatenations

* Replace some simple str.formats with f-strings

* Replace some string concatenations with f-strings
This commit is contained in:
Ville Skyttä
2020-01-03 14:47:06 +01:00
committed by Paulus Schoutsen
parent 5ad209c6fd
commit fa4fa30461
105 changed files with 241 additions and 314 deletions
+5 -9
View File
@@ -55,10 +55,8 @@ def ensure_config_path(config_dir: str) -> None:
if not os.path.isdir(config_dir):
if config_dir != config_util.get_default_config_dir():
print(
(
"Fatal Error: Specified configuration directory does "
"not exist {} "
).format(config_dir)
f"Fatal Error: Specified configuration directory {config_dir} "
"does not exist"
)
sys.exit(1)
@@ -66,10 +64,8 @@ def ensure_config_path(config_dir: str) -> None:
os.mkdir(config_dir)
except OSError:
print(
(
"Fatal Error: Unable to create default configuration "
"directory {} "
).format(config_dir)
"Fatal Error: Unable to create default configuration "
f"directory {config_dir}"
)
sys.exit(1)
@@ -78,7 +74,7 @@ def ensure_config_path(config_dir: str) -> None:
try:
os.mkdir(lib_dir)
except OSError:
print("Fatal Error: Unable to create library directory {}".format(lib_dir))
print(f"Fatal Error: Unable to create library directory {lib_dir}")
sys.exit(1)
+1 -1
View File
@@ -150,7 +150,7 @@ class ApnsNotificationService(BaseNotificationService):
self.app_name = app_name
self.sandbox = sandbox
self.certificate = cert_file
self.yaml_path = hass.config.path(app_name + "_" + APNS_DEVICES)
self.yaml_path = hass.config.path(f"{app_name}_{APNS_DEVICES}")
self.devices = {}
self.device_states = {}
self.topic = topic
@@ -291,7 +291,7 @@ class BraviaTVDevice(MediaPlayerDevice):
if self._channel_name is not None:
return_value = self._channel_name
if self._program_name is not None:
return_value = return_value + ": " + self._program_name
return_value = f"{return_value}: {self._program_name}"
return return_value
@property
+1 -1
View File
@@ -158,7 +158,7 @@ def async_remote_ui_url(hass) -> str:
if not hass.data[DOMAIN].remote.instance_domain:
raise CloudNotAvailable
return "https://" + hass.data[DOMAIN].remote.instance_domain
return f"https://{hass.data[DOMAIN].remote.instance_domain}"
def is_cloudhook_request(request):
+1 -1
View File
@@ -750,7 +750,7 @@ class DarkSkyAlertSensor(Entity):
for i, alert in enumerate(data):
for attr in ALERTS_ATTRS:
if multiple_alerts:
dkey = attr + "_" + str(i)
dkey = f"{attr}_{i!s}"
else:
dkey = attr
alerts[dkey] = getattr(alert, attr)
+1 -1
View File
@@ -34,7 +34,7 @@ def verify_ebusd_config(config):
circuit = config[CONF_CIRCUIT]
for condition in config[CONF_MONITORED_CONDITIONS]:
if condition not in SENSOR_TYPES[circuit]:
raise vol.Invalid("Condition '" + condition + "' not in '" + circuit + "'.")
raise vol.Invalid(f"Condition '{condition}' not in '{circuit}'.")
return config
@@ -18,7 +18,7 @@ from homeassistant.helpers.discovery import load_platform
_LOGGER = logging.getLogger(__name__)
DOMAIN = "ecoal_boiler"
DATA_ECOAL_BOILER = "data_" + DOMAIN
DATA_ECOAL_BOILER = f"data_{DOMAIN}"
DEFAULT_USERNAME = "admin"
DEFAULT_PASSWORD = "admin"
@@ -38,7 +38,7 @@ class EcoalSwitch(SwitchDevice):
# set_<attr>()
# as attribute name in status instance:
# status.<attr>
self._contr_set_fun = getattr(self._ecoal_contr, "set_" + state_attr)
self._contr_set_fun = getattr(self._ecoal_contr, f"set_{state_attr}")
# No value set, will be read from controller instead
self._state = None
+1 -1
View File
@@ -110,7 +110,7 @@ def setup(hass, config):
bound = server.bind()
if not bound:
raise OSError(
"Binding error occurred while " + "starting EgardiaServer."
"Binding error occurred while starting EgardiaServer."
)
hass.data[EGARDIA_SERVER] = server
server.start()
+1 -1
View File
@@ -268,7 +268,7 @@ class FibaroController:
else:
room_name = self._room_map[device.roomID].name
device.room_name = room_name
device.friendly_name = room_name + " " + device.name
device.friendly_name = f"{room_name} {device.name}"
device.ha_id = "{}_{}_{}".format(
slugify(room_name), slugify(device.name), device.id
)
@@ -86,15 +86,15 @@ class HangoutsBot:
conv_id = self._resolve_conversation_id(conversation)
if conv_id is not None:
conversations.append(conv_id)
data["_" + CONF_CONVERSATIONS] = conversations
data[f"_{CONF_CONVERSATIONS}"] = conversations
elif self._default_conv_ids:
data["_" + CONF_CONVERSATIONS] = self._default_conv_ids
data[f"_{CONF_CONVERSATIONS}"] = self._default_conv_ids
else:
data["_" + CONF_CONVERSATIONS] = [
data[f"_{CONF_CONVERSATIONS}"] = [
conv.id_ for conv in self._conversation_list.get_all()
]
for conv_id in data["_" + CONF_CONVERSATIONS]:
for conv_id in data[f"_{CONF_CONVERSATIONS}"]:
if conv_id not in self._conversation_intents:
self._conversation_intents[conv_id] = {}
+2 -4
View File
@@ -21,12 +21,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
vol.Exclusive(
CONF_PASSWORD,
"hook_secret",
msg="hook: provide " + "username/password OR token",
msg="hook: provide username/password OR token",
): cv.string,
vol.Exclusive(
CONF_TOKEN,
"hook_secret",
msg="hook: provide " + "username/password OR token",
CONF_TOKEN, "hook_secret", msg="hook: provide username/password OR token",
): cv.string,
vol.Inclusive(CONF_USERNAME, "hook_auth"): cv.string,
vol.Inclusive(CONF_PASSWORD, "hook_auth"): cv.string,
@@ -88,7 +88,7 @@ class HuaweiDeviceScanner(DeviceScanner):
_LOGGER.debug(
"Active clients: %s",
"\n".join((client.mac + " " + client.name) for client in active_clients),
"\n".join(f"{client.mac} {client.name}" for client in active_clients),
)
return True
+2 -2
View File
@@ -216,7 +216,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool
if icloud_account is None:
raise Exception(
"No iCloud account with username or name " + account_identifier
f"No iCloud account with username or name {account_identifier}"
)
return icloud_account
@@ -430,7 +430,7 @@ class IcloudAccount:
if slugify(device.name.replace(" ", "", 99)) == name_slug:
result.append(device)
if not result:
raise Exception("No device with name " + name)
raise Exception(f"No device with name {name}")
return result
@property
+1 -1
View File
@@ -614,7 +614,7 @@ class InsteonEntity(Entity):
# Get an extension label if there is one
extension = self._get_label()
if extension:
extension = " " + extension
extension = f" {extension}"
name = "{:s} {:s}{:s}".format(
description, self._insteon_device.address.human, extension
)
@@ -110,7 +110,7 @@ class Itunes:
def _command(self, named_command):
"""Make a request for a controlling command."""
return self._request("PUT", "/" + named_command)
return self._request("PUT", f"/{named_command}")
def now_playing(self):
"""Return the current state."""
@@ -168,7 +168,7 @@ class Itunes:
def artwork_url(self):
"""Return a URL of the current track's album art."""
return self._base_url + "/artwork"
return f"{self._base_url}/artwork"
def airplay_devices(self):
"""Return a list of AirPlay devices."""
@@ -176,17 +176,17 @@ class Itunes:
def airplay_device(self, device_id):
"""Return an AirPlay device."""
return self._request("GET", "/airplay_devices/" + device_id)
return self._request("GET", f"/airplay_devices/{device_id}")
def toggle_airplay_device(self, device_id, toggle):
"""Toggle airplay device on or off, id, toggle True or False."""
command = "on" if toggle else "off"
path = "/airplay_devices/" + device_id + "/" + command
path = f"/airplay_devices/{device_id}/{command}"
return self._request("PUT", path)
def set_volume_airplay_device(self, device_id, level):
"""Set volume, returns current state of device, id,level 0-100."""
path = "/airplay_devices/" + device_id + "/volume"
path = f"/airplay_devices/{device_id}/volume"
return self._request("PUT", path, {"level": level})
@@ -431,7 +431,7 @@ class AirPlayDevice(MediaPlayerDevice):
if "name" in state_hash:
name = state_hash.get("name", "")
self.device_name = (name + " AirTunes Speaker").strip()
self.device_name = f"{name} AirTunes Speaker".strip()
if "kind" in state_hash:
self.kind = state_hash.get("kind", None)
@@ -963,7 +963,7 @@ class KodiDevice(MediaPlayerDevice):
@staticmethod
def _find(key_word, words):
key_word = key_word.split(" ")
patt = [re.compile("(^| )" + k + "( |$)", re.IGNORECASE) for k in key_word]
patt = [re.compile(f"(^| ){k}( |$)", re.IGNORECASE) for k in key_word]
out = [[i, 0] for i in range(len(words))]
for i in range(len(words)):
@@ -488,7 +488,7 @@ class KonnectedView(HomeAssistantView):
device = data[CONF_DEVICES][device_id]
if not device:
return self.json_message(
"Device " + device_id + " not configured", status_code=HTTP_NOT_FOUND
f"Device {device_id} not configured", status_code=HTTP_NOT_FOUND
)
try:
@@ -162,7 +162,7 @@ class Life360Scanner:
msg = f"{key}: {err_msg}"
if _errs >= self._error_threshold:
if _errs == self._max_errs:
msg = "Suppressing further errors until OK: " + msg
msg = f"Suppressing further errors until OK: {msg}"
_LOGGER.error(msg)
elif _errs >= self._warning_threshold:
_LOGGER.warning(msg)
+1 -1
View File
@@ -562,7 +562,7 @@ class LIFXLight(Light):
"""Return the name of the currently running effect."""
effect = self.effects_conductor.effect(self.bulb)
if effect:
return "lifx_effect_" + effect.name
return f"lifx_effect_{effect.name}"
return None
async def update_hass(self, now=None):
@@ -155,9 +155,9 @@ class NetatmoBinarySensor(BinarySensorDevice):
else:
self._name = camera_name
if module_name:
self._name += " / " + module_name
self._name += f" / {module_name}"
self._sensor_name = sensor
self._name += " " + sensor
self._name += f" {sensor}"
self._cameratype = camera_type
self._state = None
+2 -2
View File
@@ -106,7 +106,7 @@ class NetatmoCamera(Camera):
self._camera_name = camera_name
self._home = home
if home:
self._name = home + " / " + camera_name
self._name = f"{home} / {camera_name}"
else:
self._name = camera_name
self._cameratype = camera_type
@@ -383,7 +383,7 @@ class NetatmoCamera(Camera):
"""Set light mode ('auto', 'on', 'off')."""
if self.model == "Presence":
try:
config = '{"mode":"' + mode + '"}'
config = f'{{"mode":"{mode}"}}'
if self._localurl:
requests.get(
f"{self._localurl}/command/floodlight_set_config?config={config}",
@@ -116,7 +116,7 @@ class NetgearDeviceScanner(DeviceScanner):
self.tracked_accesspoints
and dev.conn_ap_mac in self.tracked_accesspoints
):
devices.append(dev.mac + "_" + dev.conn_ap_mac)
devices.append(f"{dev.mac}_{dev.conn_ap_mac}")
return devices
@@ -144,7 +144,7 @@ class NetgearDeviceScanner(DeviceScanner):
ap_name = dev.name
break
return name + " on " + ap_name
return f"{name} on {ap_name}"
return name
@@ -45,7 +45,7 @@ def ensure_valid_path(value):
"""Validate the path, ensuring it starts and ends with a /."""
vol.Schema(cv.string)(value)
if value[0] != "/":
value = "/" + value
value = f"/{value}"
if value[-1] != "/":
value += "/"
return value
@@ -189,7 +189,7 @@ class OctoPrintAPI:
tools = []
if self.number_of_tools > 0:
for tool_number in range(0, self.number_of_tools):
tools.append("tool" + str(tool_number))
tools.append(f"tool{tool_number!s}")
if self.bed:
tools.append("bed")
if not self.bed and self.number_of_tools == 0:
@@ -231,18 +231,16 @@ class OctoPrintAPI:
self.printer_error_logged = False
return response.json()
except Exception as conn_exc: # pylint: disable=broad-except
log_string = "Failed to update OctoPrint status. " + " Error: %s" % (
conn_exc
)
log_string = "Failed to update OctoPrint status. Error: %s" % conn_exc
# Only log the first failure
if endpoint == "job":
log_string = "Endpoint: job " + log_string
log_string = f"Endpoint: job {log_string}"
if not self.job_error_logged:
_LOGGER.error(log_string)
self.job_error_logged = True
self.job_available = False
elif endpoint == "printer":
log_string = "Endpoint: printer " + log_string
log_string = f"Endpoint: printer {log_string}"
if not self.printer_error_logged:
_LOGGER.error(log_string)
self.printer_error_logged = True
+1 -1
View File
@@ -148,7 +148,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
# We have a raw GPIO ow sensor on a Pi
elif base_dir == DEFAULT_MOUNT_DIR:
for device_family in DEVICE_SENSORS:
for device_folder in glob(os.path.join(base_dir, device_family + "[.-]*")):
for device_folder in glob(os.path.join(base_dir, f"{device_family}[.-]*")):
sensor_id = os.path.split(device_folder)[1]
device_file = os.path.join(device_folder, "w1_slave")
devs.append(
+9 -9
View File
@@ -44,15 +44,15 @@ ATTR_MAX_BRIGHTNESS_HISTORY = "max_brightness"
# to have a separate literal for it to avoid confusion.
ATTR_DICT_OF_UNITS_OF_MEASUREMENT = "unit_of_measurement_dict"
CONF_MIN_BATTERY_LEVEL = "min_" + READING_BATTERY
CONF_MIN_TEMPERATURE = "min_" + READING_TEMPERATURE
CONF_MAX_TEMPERATURE = "max_" + READING_TEMPERATURE
CONF_MIN_MOISTURE = "min_" + READING_MOISTURE
CONF_MAX_MOISTURE = "max_" + READING_MOISTURE
CONF_MIN_CONDUCTIVITY = "min_" + READING_CONDUCTIVITY
CONF_MAX_CONDUCTIVITY = "max_" + READING_CONDUCTIVITY
CONF_MIN_BRIGHTNESS = "min_" + READING_BRIGHTNESS
CONF_MAX_BRIGHTNESS = "max_" + READING_BRIGHTNESS
CONF_MIN_BATTERY_LEVEL = f"min_{READING_BATTERY}"
CONF_MIN_TEMPERATURE = f"min_{READING_TEMPERATURE}"
CONF_MAX_TEMPERATURE = f"max_{READING_TEMPERATURE}"
CONF_MIN_MOISTURE = f"min_{READING_MOISTURE}"
CONF_MAX_MOISTURE = f"max_{READING_MOISTURE}"
CONF_MIN_CONDUCTIVITY = f"min_{READING_CONDUCTIVITY}"
CONF_MAX_CONDUCTIVITY = f"max_{READING_CONDUCTIVITY}"
CONF_MIN_BRIGHTNESS = f"min_{READING_BRIGHTNESS}"
CONF_MAX_BRIGHTNESS = f"max_{READING_BRIGHTNESS}"
CONF_CHECK_DAYS = "check_days"
CONF_SENSOR_BATTERY_LEVEL = READING_BATTERY
@@ -300,7 +300,7 @@ class PlexMediaPlayer(MediaPlayerDevice):
elif self._session_type == "movie":
self._media_content_type = MEDIA_TYPE_MOVIE
if self.session.year is not None and self._media_title is not None:
self._media_title += " (" + str(self.session.year) + ")"
self._media_title += f" ({self.session.year!s})"
elif self._session_type == "track":
self._media_content_type = MEDIA_TYPE_MUSIC
@@ -50,7 +50,7 @@ def log_message(source, *parts):
"""Build log message."""
message = source.__class__.__name__
for part in parts:
message += ": " + str(part)
message += f": {part!s}"
return message
+3 -3
View File
@@ -127,7 +127,7 @@ class I2CHatSwitch(ToggleEntity):
state = self.I2C_HATS_MANAGER.read_dq(self._address, self._channel)
return state != self._invert_logic
except I2CHatsException as ex:
_LOGGER.error(self._log_message("Is ON check failed, " + str(ex)))
_LOGGER.error(self._log_message(f"Is ON check failed, {ex!s}"))
return False
def turn_on(self, **kwargs):
@@ -137,7 +137,7 @@ class I2CHatSwitch(ToggleEntity):
self.I2C_HATS_MANAGER.write_dq(self._address, self._channel, state)
self.schedule_update_ha_state()
except I2CHatsException as ex:
_LOGGER.error(self._log_message("Turn ON failed, " + str(ex)))
_LOGGER.error(self._log_message(f"Turn ON failed, {ex!s}"))
def turn_off(self, **kwargs):
"""Turn the device off."""
@@ -146,4 +146,4 @@ class I2CHatSwitch(ToggleEntity):
self.I2C_HATS_MANAGER.write_dq(self._address, self._channel, state)
self.schedule_update_ha_state()
except I2CHatsException as ex:
_LOGGER.error(self._log_message("Turn OFF failed:, " + str(ex)))
_LOGGER.error(self._log_message(f"Turn OFF failed, {ex!s}"))
@@ -344,7 +344,7 @@ class SamsungTVDevice(MediaPlayerDevice):
return
for digit in media_id:
await self.hass.async_add_job(self.send_key, "KEY_" + digit)
await self.hass.async_add_job(self.send_key, f"KEY_{digit}")
await asyncio.sleep(KEY_PRESS_TIMEOUT, self.hass.loop)
await self.hass.async_add_job(self.send_key, "KEY_ENTER")
+1 -1
View File
@@ -65,7 +65,7 @@ _FETCH_FIELDS = ",".join(
"temperatureUnit",
]
)
_INITIAL_FETCH_FIELDS = "id," + _FETCH_FIELDS
_INITIAL_FETCH_FIELDS = f"id,{_FETCH_FIELDS}"
FIELD_TO_FLAG = {
"fanLevel": SUPPORT_FAN_MODE,
@@ -45,7 +45,7 @@ ENTITY_ID_TEMPLATE = "sensor.seventeentrack_package_{0}"
NOTIFICATION_DELIVERED_ID = "package_delivered_{0}"
NOTIFICATION_DELIVERED_TITLE = "Package {0} delivered"
NOTIFICATION_DELIVERED_MESSAGE = (
"Package Delivered: {0}<br />" + "Visit 17.track for more information: "
"Package Delivered: {0}<br />Visit 17.track for more information: "
"https://t.17track.net/track#nums={1}"
)
@@ -95,8 +95,7 @@ def _parse_skyhub_response(data_str):
pattmatch = re.search("attach_dev = '(.*)'", data_str)
if pattmatch is None:
raise OSError(
"Error: Impossible to fetch data from"
+ " Sky Hub. Try to reboot the router."
"Error: Impossible to fetch data from Sky Hub. Try to reboot the router."
)
patt = pattmatch.group(1)
@@ -107,8 +106,6 @@ def _parse_skyhub_response(data_str):
if _MAC_REGEX.match(dvc[1]):
devices[dvc[1]] = dvc[0]
else:
raise RuntimeError(
"Error: MAC address " + dvc[1] + " not in correct format."
)
raise RuntimeError(f"Error: MAC address {dvc[1]} not in correct format.")
return devices
+1 -1
View File
@@ -24,7 +24,7 @@ CONF_HOST_PASSWORD = "host_password"
DOMAIN = "smappee"
DATA_SMAPPEE = "SMAPPEE"
_SENSOR_REGEX = re.compile(r"(?P<key>([A-Za-z]+))\=" + r"(?P<value>([0-9\.]+))")
_SENSOR_REGEX = re.compile(r"(?P<key>([A-Za-z]+))\=(?P<value>([0-9\.]+))")
CONFIG_SCHEMA = vol.Schema(
{
@@ -279,7 +279,7 @@ class DeviceBroker:
capabilities = device.capabilities.copy()
slots = {}
for platform_name in SUPPORTED_PLATFORMS:
platform = importlib.import_module("." + platform_name, self.__module__)
platform = importlib.import_module(f".{platform_name}", self.__module__)
if not hasattr(platform, "get_capabilities"):
continue
assigned = platform.get_capabilities(capabilities)
@@ -109,7 +109,7 @@ def get_webhook_url(hass: HomeAssistantType) -> str:
def _get_app_template(hass: HomeAssistantType):
endpoint = "at " + hass.config.api.base_url
endpoint = f"at {hass.config.api.base_url}"
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if cloudhook_url is not None:
endpoint = "via Nabu Casa"
@@ -304,7 +304,7 @@ class SoundTouchDevice(MediaPlayerDevice):
if self._status.station_name is not None:
return self._status.station_name
if self._status.artist is not None:
return self._status.artist + " - " + self._status.track
return f"{self._status.artist} - {self._status.track}"
return None
+1 -1
View File
@@ -140,7 +140,7 @@ class StartcaData:
async def async_update(self):
"""Get the Start.ca bandwidth data from the web service."""
_LOGGER.debug("Updating Start.ca usage data")
url = "https://www.start.ca/support/usage/api?key=" + self.api_key
url = f"https://www.start.ca/support/usage/api?key={self.api_key}"
with async_timeout.timeout(REQUEST_TIMEOUT):
req = await self.websession.get(url)
if req.status != 200:
@@ -73,7 +73,7 @@ class TankUtilitySensor(Entity):
self._token = token
self._device = device
self._state = None
self._name = "Tank Utility " + self.device
self._name = f"Tank Utility {self.device}"
self._unit_of_measurement = SENSOR_UNIT_OF_MEASUREMENT
self._attributes = {}
+1 -1
View File
@@ -39,7 +39,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
for idx, dev in enumerate(temper_devices):
if idx != 0:
name = name + "_" + str(idx)
name = f"{name}_{idx!s}"
TEMPER_SENSORS.append(TemperSensor(dev, temp_unit, name, scaling))
add_entities(TEMPER_SENSORS)
@@ -998,7 +998,7 @@ class WUndergroundSensor(Entity):
self.rest.request_feature(SENSOR_TYPES[condition].feature)
# This is only the suggested entity id, it might get changed by
# the entity registry later.
self.entity_id = sensor.ENTITY_ID_FORMAT.format("pws_" + condition)
self.entity_id = sensor.ENTITY_ID_FORMAT.format(f"pws_{condition}")
self._unique_id = f"{unique_id_base},{condition}"
self._device_class = self._cfg_expand("device_class")
@@ -1122,11 +1122,11 @@ class WUndergroundData:
self._api_key, "/".join(sorted(self._features)), self._lang
)
if self._pws_id:
url = url + f"pws:{self._pws_id}"
url = f"{url}pws:{self._pws_id}"
else:
url = url + f"{self._latitude},{self._longitude}"
url = f"{url}{self._latitude},{self._longitude}"
return url + ".json"
return f"{url}.json"
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self):
+5 -5
View File
@@ -34,7 +34,7 @@ def x10_command(command):
def get_unit_status(code):
"""Get on/off status for given unit."""
output = check_output("heyu onstate " + code, shell=True)
output = check_output(f"heyu onstate {code}", shell=True)
return int(output.decode("utf-8")[0])
@@ -84,18 +84,18 @@ class X10Light(Light):
def turn_on(self, **kwargs):
"""Instruct the light to turn on."""
if self._is_cm11a:
x10_command("on " + self._id)
x10_command(f"on {self._id}")
else:
x10_command("fon " + self._id)
x10_command(f"fon {self._id}")
self._brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
self._state = True
def turn_off(self, **kwargs):
"""Instruct the light to turn off."""
if self._is_cm11a:
x10_command("off " + self._id)
x10_command(f"off {self._id}")
else:
x10_command("foff " + self._id)
x10_command(f"foff {self._id}")
self._state = False
def update(self):
+1 -1
View File
@@ -935,6 +935,6 @@ class YeelightAmbientLight(YeelightColorLight):
bg_prop = self.PROPERTIES_MAPPING.get(prop)
if not bg_prop:
bg_prop = "bg_" + prop
bg_prop = f"bg_{prop}"
return super()._get_property(bg_prop, default)
+1 -1
View File
@@ -797,7 +797,7 @@ async def async_binding_operation(zha_gateway, source_ieee, target_ieee, operati
operation.name,
target_ieee,
)
zdo.debug("processing " + op_msg, *op_params)
zdo.debug(f"processing {op_msg}", *op_params)
bind_tasks.append(
(
@@ -263,7 +263,7 @@ class ZigbeeChannel(LogMixin):
def log(self, level, msg, *args):
"""Log a message."""
msg = "[%s:%s]: " + msg
msg = f"[%s:%s]: {msg}"
args = (self.device.nwk, self._id,) + args
_LOGGER.log(level, msg, *args)
@@ -357,7 +357,7 @@ class ZDOChannel(LogMixin):
def log(self, level, msg, *args):
"""Log a message."""
msg = "[%s:ZDO](%s): " + msg
msg = f"[%s:ZDO](%s): {msg}"
args = (self._zha_device.nwk, self._zha_device.model) + args
_LOGGER.log(level, msg, *args)
+1 -1
View File
@@ -528,6 +528,6 @@ class ZHADevice(LogMixin):
def log(self, level, msg, *args):
"""Log a message."""
msg = "[%s](%s): " + msg
msg = f"[%s](%s): {msg}"
args = (self.nwk, self.model) + args
_LOGGER.log(level, msg, *args)
+1 -1
View File
@@ -185,6 +185,6 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity):
def log(self, level, msg, *args):
"""Log a message."""
msg = "%s: " + msg
msg = f"%s: {msg}"
args = (self.entity_id,) + args
_LOGGER.log(level, msg, *args)
@@ -161,9 +161,7 @@ class ZhongHongClimate(ClimateDevice):
@property
def unique_id(self):
"""Return the unique ID of the HVAC."""
return "zhong_hong_hvac_{}_{}".format(
self._device.addr_out, self._device.addr_in
)
return f"zhong_hong_hvac_{self._device.addr_out}_{self._device.addr_in}"
@property
def supported_features(self):
+1 -1
View File
@@ -37,7 +37,7 @@ def _to_hex_str(id_in_bytes):
Example: 0x1234 --> '0x1234'
"""
return "0x{:04x}".format(id_in_bytes)
return f"0x{id_in_bytes:04x}"
# For some reason node.manufacturer_id is of type string. So we need to convert
+1 -3
View File
@@ -572,9 +572,7 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: Dict) -> Non
def _log_pkg_error(package: str, component: str, config: Dict, message: str) -> None:
"""Log an error while merging packages."""
message = "Package {} setup failed. Integration {} {}".format(
package, component, message
)
message = f"Package {package} setup failed. Integration {component} {message}"
pack_config = config[CONF_CORE][CONF_PACKAGES].get(package, config)
message += " (See {}:{}). ".format(
+2 -2
View File
@@ -2,8 +2,8 @@
MAJOR_VERSION = 0
MINOR_VERSION = 104
PATCH_VERSION = "0.dev0"
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION)
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 7, 0)
# Truthy date string triggers showing related deprecation warning messages.
REQUIRED_NEXT_PYTHON_VER = (3, 8, 0)
+5 -11
View File
@@ -712,18 +712,14 @@ class State:
if not valid_entity_id(entity_id) and not temp_invalid_id_bypass:
raise InvalidEntityFormatError(
(
"Invalid entity id encountered: {}. "
"Format should be <domain>.<object_id>"
).format(entity_id)
f"Invalid entity id encountered: {entity_id}. "
"Format should be <domain>.<object_id>"
)
if not valid_state(state):
raise InvalidStateError(
(
"Invalid state encountered for entity id: {}. "
"State max length is 255 characters."
).format(entity_id)
f"Invalid state encountered for entity id: {entity_id}. "
"State max length is 255 characters."
)
self.entity_id = entity_id.lower()
@@ -1034,9 +1030,7 @@ class ServiceCall:
self.domain, self.service, self.context.id, util.repr_helper(self.data)
)
return "<ServiceCall {}.{} (c:{})>".format(
self.domain, self.service, self.context.id
)
return f"<ServiceCall {self.domain}.{self.service} (c:{self.context.id})>"
class ServiceRegistry:
+1 -3
View File
@@ -153,9 +153,7 @@ class FlowManager(abc.ABC):
if not hasattr(flow, method):
self._progress.pop(flow.flow_id)
raise UnknownStep(
"Handler {} doesn't support step {}".format(
flow.__class__.__name__, step_id
)
f"Handler {flow.__class__.__name__} doesn't support step {step_id}"
)
try:
+1 -1
View File
@@ -36,5 +36,5 @@ def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
Async friendly.
"""
pattern = re.compile(r"^{}(| .+)$".format(domain))
pattern = re.compile(fr"^{domain}(| .+)$")
return [key for key in config.keys() if pattern.match(key)]
+1 -3
View File
@@ -69,9 +69,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
package: str, component: str, config: ConfigType, message: str
) -> None:
"""Handle errors from packages: _log_pkg_error."""
message = "Package {} setup failed. Component {} {}".format(
package, component, message
)
message = f"Package {package} setup failed. Component {component} {message}"
domain = f"homeassistant.packages.{package}.{component}"
pack_config = core_config[CONF_PACKAGES].get(package, config)
result.add_error(message, domain, pack_config)
+19 -23
View File
@@ -135,7 +135,7 @@ def boolean(value: Any) -> bool:
elif isinstance(value, Number):
# type ignore: https://github.com/python/mypy/issues/3186
return value != 0 # type: ignore
raise vol.Invalid("invalid boolean value {}".format(value))
raise vol.Invalid(f"invalid boolean value {value}")
def isdevice(value: Any) -> str:
@@ -144,7 +144,7 @@ def isdevice(value: Any) -> str:
os.stat(value)
return str(value)
except OSError:
raise vol.Invalid("No device at {} found".format(value))
raise vol.Invalid(f"No device at {value} found")
def matches_regex(regex: str) -> Callable[[Any], str]:
@@ -154,13 +154,11 @@ def matches_regex(regex: str) -> Callable[[Any], str]:
def validator(value: Any) -> str:
"""Validate that value matches the given regex."""
if not isinstance(value, str):
raise vol.Invalid("not a string value: {}".format(value))
raise vol.Invalid(f"not a string value: {value}")
if not compiled.match(value):
raise vol.Invalid(
"value {} does not match regular expression {}".format(
value, compiled.pattern
)
f"value {value} does not match regular expression {compiled.pattern}"
)
return value
@@ -175,10 +173,10 @@ def is_regex(value: Any) -> Pattern[Any]:
return r
except TypeError:
raise vol.Invalid(
"value {} is of the wrong type for a regular expression".format(value)
f"value {value} is of the wrong type for a regular expression"
)
except re.error:
raise vol.Invalid("value {} is not a valid regular expression".format(value))
raise vol.Invalid(f"value {value} is not a valid regular expression")
def isfile(value: Any) -> str:
@@ -220,7 +218,7 @@ def entity_id(value: Any) -> str:
if valid_entity_id(str_value):
return str_value
raise vol.Invalid("Entity ID {} is an invalid entity id".format(value))
raise vol.Invalid(f"Entity ID {value} is an invalid entity id")
def entity_ids(value: Union[str, List]) -> List[str]:
@@ -256,9 +254,7 @@ def entities_domain(domain: str) -> Callable[[Union[str, List]], List[str]]:
for ent_id in values:
if split_entity_id(ent_id)[0] != domain:
raise vol.Invalid(
"Entity ID '{}' does not belong to domain '{}'".format(
ent_id, domain
)
f"Entity ID '{ent_id}' does not belong to domain '{domain}'"
)
return values
@@ -307,7 +303,7 @@ def time(value: Any) -> time_sys:
raise vol.Invalid("Not a parseable type")
if time_val is None:
raise vol.Invalid("Invalid time specified: {}".format(value))
raise vol.Invalid(f"Invalid time specified: {value}")
return time_val
@@ -368,7 +364,7 @@ def time_period_seconds(value: Union[int, str]) -> timedelta:
try:
return timedelta(seconds=int(value))
except (ValueError, TypeError):
raise vol.Invalid("Expected seconds, got {}".format(value))
raise vol.Invalid(f"Expected seconds, got {value}")
time_period = vol.Any(time_period_str, time_period_seconds, timedelta, time_period_dict)
@@ -400,7 +396,7 @@ def service(value: Any) -> str:
str_value = string(value).lower()
if valid_entity_id(str_value):
return str_value
raise vol.Invalid("Service {} does not match format <domain>.<name>".format(value))
raise vol.Invalid(f"Service {value} does not match format <domain>.<name>")
def schema_with_slug_keys(value_schema: Union[T, Callable]) -> Callable:
@@ -432,7 +428,7 @@ def slug(value: Any) -> str:
slg = util_slugify(str_value)
if str_value == slg:
return str_value
raise vol.Invalid("invalid slug {} (try {})".format(value, slg))
raise vol.Invalid(f"invalid slug {value} (try {slg})")
def slugify(value: Any) -> str:
@@ -442,7 +438,7 @@ def slugify(value: Any) -> str:
slg = util_slugify(str(value))
if slg:
return slg
raise vol.Invalid("Unable to slugify {}".format(value))
raise vol.Invalid(f"Unable to slugify {value}")
def string(value: Any) -> str:
@@ -484,7 +480,7 @@ def template(value: Optional[Any]) -> template_helper.Template:
template_value.ensure_valid()
return cast(template_helper.Template, template_value)
except TemplateError as ex:
raise vol.Invalid("invalid template ({})".format(ex))
raise vol.Invalid(f"invalid template ({ex})")
def template_complex(value: Any) -> Any:
@@ -515,7 +511,7 @@ def datetime(value: Any) -> datetime_sys:
date_val = None
if date_val is None:
raise vol.Invalid("Invalid datetime specified: {}".format(value))
raise vol.Invalid(f"Invalid datetime specified: {value}")
return date_val
@@ -545,8 +541,8 @@ def socket_timeout(value: Optional[Any]) -> object:
if float_value > 0.0:
return float_value
raise vol.Invalid("Invalid socket timeout value. float > 0.0 required.")
except Exception as _:
raise vol.Invalid("Invalid socket timeout: {err}".format(err=_))
except Exception as err:
raise vol.Invalid(f"Invalid socket timeout: {err}")
# pylint: disable=no-value-for-parameter
@@ -700,8 +696,8 @@ def key_dependency(
raise vol.Invalid("key dependencies require a dict")
if key in value and dependency not in value:
raise vol.Invalid(
'dependency violation - key "{}" requires '
'key "{}" to exist'.format(key, dependency)
f'dependency violation - key "{key}" requires '
f'key "{dependency}" to exist'
)
return value
+2 -2
View File
@@ -65,7 +65,7 @@ def discover(hass, service, discovered, component, hass_config):
async def async_discover(hass, service, discovered, component, hass_config):
"""Fire discovery event. Can ensure a component is loaded."""
if component in DEPENDENCY_BLACKLIST:
raise HomeAssistantError("Cannot discover the {} component.".format(component))
raise HomeAssistantError(f"Cannot discover the {component} component.")
if component is not None and component not in hass.config.components:
await setup.async_setup_component(hass, component, hass_config)
@@ -151,7 +151,7 @@ async def async_load_platform(hass, component, platform, discovered, hass_config
assert hass_config, "You need to pass in the real hass config"
if component in DEPENDENCY_BLACKLIST:
raise HomeAssistantError("Cannot discover the {} component.".format(component))
raise HomeAssistantError(f"Cannot discover the {component} component.")
setup_success = True
+1 -1
View File
@@ -562,7 +562,7 @@ class Entity(ABC):
def __repr__(self) -> str:
"""Return the representation."""
return "<Entity {}: {}>".format(self.name, self.state)
return f"<Entity {self.name}: {self.state}>"
# call an requests
async def async_request_call(self, coro):
+3 -9
View File
@@ -304,9 +304,7 @@ class EntityPlatform:
suggested_object_id = entity.name
if self.entity_namespace is not None:
suggested_object_id = "{} {}".format(
self.entity_namespace, suggested_object_id
)
suggested_object_id = f"{self.entity_namespace} {suggested_object_id}"
if self.config_entry is not None:
config_entry_id = self.config_entry.entry_id
@@ -380,9 +378,7 @@ class EntityPlatform:
)
if self.entity_namespace is not None:
suggested_object_id = "{} {}".format(
self.entity_namespace, suggested_object_id
)
suggested_object_id = f"{self.entity_namespace} {suggested_object_id}"
entity.entity_id = entity_registry.async_generate_entity_id(
self.domain, suggested_object_id, self.entities.keys()
)
@@ -402,9 +398,7 @@ class EntityPlatform:
if already_exists:
msg = f"Entity id already exists: {entity.entity_id}"
if entity.unique_id is not None:
msg += ". Platform {} does not generate unique IDs".format(
self.platform_name
)
msg += f". Platform {self.platform_name} does not generate unique IDs"
raise HomeAssistantError(msg)
entity_id = entity.entity_id
+2 -3
View File
@@ -323,9 +323,8 @@ class EntityRegistry:
)
if conflict:
raise ValueError(
"Unique id '{}' is already in use by '{}'".format(
new_unique_id, conflict.entity_id
)
f"Unique id '{new_unique_id}' is already in use by "
f"'{conflict.entity_id}'"
)
changes["unique_id"] = new_unique_id
+1 -1
View File
@@ -8,7 +8,7 @@ def icon_for_battery_level(
"""Return a battery icon valid identifier."""
icon = "mdi:battery"
if battery_level is None:
return icon + "-unknown"
return f"{icon}-unknown"
if charging and battery_level > 10:
icon += "-charging-{}".format(int(round(battery_level / 20 - 0.01)) * 20)
elif charging:
+1 -1
View File
@@ -158,7 +158,7 @@ class IntentHandler:
def __repr__(self) -> str:
"""Represent a string of an intent handler."""
return "<{} - {}>".format(self.__class__.__name__, self.intent_type)
return f"<{self.__class__.__name__} - {self.intent_type}>"
def _fuzzymatch(name: str, items: Iterable[T], key: Callable[[T], str]) -> Optional[T]:
+3 -3
View File
@@ -299,7 +299,7 @@ class Script:
_LOGGER.error("Error rendering '%s' delay template: %s", self.name, ex)
raise _StopScript
self.last_action = action.get(CONF_ALIAS, "delay {}".format(delay))
self.last_action = action.get(CONF_ALIAS, f"delay {delay}")
self._log("Executing step %s" % self.last_action)
unsub = async_track_point_in_utc_time(
@@ -408,7 +408,7 @@ class Script:
self.last_action = action.get(CONF_ALIAS, action[CONF_CONDITION])
check = config(self.hass, variables)
self._log("Test condition {}: {}".format(self.last_action, check))
self._log(f"Test condition {self.last_action}: {check}")
if not check:
raise _StopScript
@@ -446,6 +446,6 @@ class Script:
def _log(self, msg):
"""Logger helper."""
if self.name is not None:
msg = "Script {}: {}".format(self.name, msg)
msg = f"Script {self.name}: {msg}"
_LOGGER.info(msg)
+1 -1
View File
@@ -240,7 +240,7 @@ def async_set_service_schema(hass, domain, service, schema):
"fields": schema.get("fields") or {},
}
hass.data[SERVICE_DESCRIPTION_CACHE]["{}.{}".format(domain, service)] = description
hass.data[SERVICE_DESCRIPTION_CACHE][f"{domain}.{service}"] = description
@bind_hass
+2 -2
View File
@@ -328,7 +328,7 @@ class AllStates:
if not valid_entity_id(name):
raise TemplateError(f"Invalid entity ID '{name}'")
return _get_state(self._hass, name)
if not valid_entity_id(name + ".entity"):
if not valid_entity_id(f"{name}.entity"):
raise TemplateError(f"Invalid domain name '{name}'")
return DomainStates(self._hass, name)
@@ -451,7 +451,7 @@ class TemplateState(State):
"""Representation of Template State."""
state = object.__getattribute__(self, "_access_state")()
rep = state.__repr__()
return "<template " + rep[1:]
return f"<template {rep[1:]}"
def _collect_state(hass, entity_id):
+1 -1
View File
@@ -53,7 +53,7 @@ async def component_translation_file(
assert integration is not None, domain
if is_platform:
filename = "{}.{}.json".format(parts[0], language)
filename = f"{parts[0]}.{language}.json"
return str(integration.file_path / ".translations" / filename)
# If it's a component that is just one file, we don't support translations
+1 -1
View File
@@ -38,7 +38,7 @@ def run(args: List) -> int:
print("Available scripts:", ", ".join(scripts))
return 1
script = importlib.import_module("homeassistant.scripts." + args[0])
script = importlib.import_module(f"homeassistant.scripts.{args[0]}")
config_dir = extract_config_dir()
+1 -1
View File
@@ -43,7 +43,7 @@ def color(the_color, *args, reset=None):
return parse_colors(the_color)
return parse_colors(the_color) + " ".join(args) + escape_codes[reset or "reset"]
except KeyError as k:
raise ValueError("Invalid color {} in {}".format(str(k), the_color))
raise ValueError(f"Invalid color {k!s} in {the_color}")
def run(script_args: List) -> int:
+3 -3
View File
@@ -27,10 +27,10 @@ def install_osx():
with open(path, "w", encoding="utf-8") as outp:
outp.write(plist)
except OSError as err:
print("Unable to write to " + path, err)
print(f"Unable to write to {path}", err)
return
os.popen("launchctl load -w -F " + path)
os.popen(f"launchctl load -w -F {path}")
print(
"Home Assistant has been installed. \
@@ -41,7 +41,7 @@ def install_osx():
def uninstall_osx():
"""Unload from launchd on OS X."""
path = os.path.expanduser("~/Library/LaunchAgents/org.homeassistant.plist")
os.popen("launchctl unload " + path)
os.popen(f"launchctl unload {path}")
print("Home Assistant has been uninstalled.")
+2 -2
View File
@@ -191,8 +191,8 @@ async def _async_setup_component(
return False
if result is not True:
log_error(
"Integration {!r} did not return boolean if setup was "
"successful. Disabling component.".format(domain)
f"Integration {domain!r} did not return boolean if setup was "
"successful. Disabling component."
)
return False
+2 -2
View File
@@ -232,8 +232,8 @@ def parse_time_expression(parameter: Any, min_value: int, max_value: int) -> Lis
for val in res:
if val < min_value or val > max_value:
raise ValueError(
"Time expression '{}': parameter {} out of range ({} to {})"
"".format(parameter, val, min_value, max_value)
f"Time expression '{parameter}': parameter {val} out of range "
f"({min_value} to {max_value})"
)
return res
+1 -1
View File
@@ -114,7 +114,7 @@ def save_yaml(fname: str, data: JSON_TYPE) -> None:
"""Save a YAML file."""
yaml = YAML(typ="rt")
yaml.indent(sequence=4, offset=2)
tmp_fname = fname + "__TEMP__"
tmp_fname = f"{fname}__TEMP__"
try:
try:
file_stat = os.stat(fname)
+4 -4
View File
@@ -107,7 +107,7 @@ class UnitSystem:
def temperature(self, temperature: float, from_unit: str) -> float:
"""Convert the given temperature to this unit system."""
if not isinstance(temperature, Number):
raise TypeError("{} is not a numeric value.".format(str(temperature)))
raise TypeError(f"{temperature!s} is not a numeric value.")
# type ignore: https://github.com/python/mypy/issues/7207
return temperature_util.convert( # type: ignore
@@ -117,7 +117,7 @@ class UnitSystem:
def length(self, length: Optional[float], from_unit: str) -> float:
"""Convert the given length to this unit system."""
if not isinstance(length, Number):
raise TypeError("{} is not a numeric value.".format(str(length)))
raise TypeError(f"{length!s} is not a numeric value.")
# type ignore: https://github.com/python/mypy/issues/7207
return distance_util.convert( # type: ignore
@@ -127,7 +127,7 @@ class UnitSystem:
def pressure(self, pressure: Optional[float], from_unit: str) -> float:
"""Convert the given pressure to this unit system."""
if not isinstance(pressure, Number):
raise TypeError("{} is not a numeric value.".format(str(pressure)))
raise TypeError(f"{pressure!s} is not a numeric value.")
# type ignore: https://github.com/python/mypy/issues/7207
return pressure_util.convert( # type: ignore
@@ -137,7 +137,7 @@ class UnitSystem:
def volume(self, volume: Optional[float], from_unit: str) -> float:
"""Convert the given volume to this unit system."""
if not isinstance(volume, Number):
raise TypeError("{} is not a numeric value.".format(str(volume)))
raise TypeError(f"{volume!s} is not a numeric value.")
# type ignore: https://github.com/python/mypy/issues/7207
return volume_util.convert( # type: ignore