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 15:47:06 +02:00 committed by Paulus Schoutsen
parent 5ad209c6fd
commit fa4fa30461
105 changed files with 241 additions and 314 deletions

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)
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)

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

View file

@ -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

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):

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)

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

View file

@ -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"

View file

@ -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

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()

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
)

View file

@ -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] = {}

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,

View file

@ -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

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

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
)

View file

@ -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)

View file

@ -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)):

View file

@ -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:

View file

@ -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)

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):

View file

@ -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

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}",

View file

@ -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

View file

@ -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

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(

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

View file

@ -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

View file

@ -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

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}"))

View file

@ -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")

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,

View file

@ -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}"
)

View file

@ -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

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(
{

View file

@ -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)

View file

@ -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"

View file

@ -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

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:

View file

@ -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 = {}

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)

View file

@ -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):

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):

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)

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(
(

View file

@ -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)

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)

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)

View file

@ -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):

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

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(

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)

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: {}. "
f"Invalid entity id encountered: {entity_id}. "
"Format should be <domain>.<object_id>"
).format(entity_id)
)
if not valid_state(state):
raise InvalidStateError(
(
"Invalid state encountered for entity id: {}. "
f"Invalid state encountered for entity id: {entity_id}. "
"State max length is 255 characters."
).format(entity_id)
)
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:

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:

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)]

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)

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

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

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):

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

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

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:

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]:

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)

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

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):

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

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()

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:

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.")

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

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

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)

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

View file

@ -182,7 +182,7 @@ def gather_requirements_from_modules(errors, reqs):
try:
module = importlib.import_module(package)
except ImportError as err:
print("{}: {}".format(package.replace(".", "/") + ".py", err))
print("{}.py: {}".format(package.replace(".", "/"), err))
errors.append(package)
continue
@ -288,8 +288,8 @@ def diff_file(filename, content):
"""Diff a file."""
return list(
difflib.context_diff(
[line + "\n" for line in Path(filename).read_text().split("\n")],
[line + "\n" for line in content.split("\n")],
[f"{line}\n" for line in Path(filename).read_text().split("\n")],
[f"{line}\n" for line in content.split("\n")],
filename,
"generated",
)

View file

@ -222,9 +222,8 @@ def validate_dependencies(
):
integration.add_error(
"dependencies",
"Using component {} but it's not in 'dependencies' or 'after_dependencies'".format(
domain
),
f"Using component {domain} but it's not in 'dependencies' "
"or 'after_dependencies'",
)

View file

@ -50,9 +50,9 @@ class Integration:
init = fil / "__init__.py"
if not init.exists():
print(
"Warning: {} missing, skipping directory. "
f"Warning: {init} missing, skipping directory. "
"If this is your development environment, "
"you can safely delete this folder.".format(init)
"you can safely delete this folder."
)
continue

View file

@ -39,8 +39,7 @@ def main():
if hasattr(module, "CONFIG_SCHEMA"):
add_msg(
"WARNING",
"Module {} contains PLATFORM and CONFIG "
"schemas".format(module_name),
f"Module {module_name} contains PLATFORM and CONFIG schemas",
)
add_msg("PLATFORM SCHEMA", module_name)
continue
@ -52,7 +51,7 @@ def main():
schema_type, schema = _identify_config_schema(module)
add_msg(
"CONFIG_SCHEMA " + str(schema_type),
f"CONFIG_SCHEMA {schema_type}",
module_name + " " + color("cyan", str(schema)[:60]),
)

View file

@ -76,8 +76,7 @@ async def async_exec(*args, display=False):
proc = await asyncio.create_subprocess_exec(*args, **kwargs)
except FileNotFoundError as err:
printc(
FAIL,
"Could not execute {}. Did you install test requirements?".format(args[0]),
FAIL, f"Could not execute {args[0]}. Did you install test requirements?",
)
raise err
@ -202,7 +201,7 @@ async def main():
elif parts[-1] == "__main__.py":
parts[-1] = "test_main.py"
else:
parts[-1] = "test_" + parts[-1]
parts[-1] = f"test_{parts[-1]}"
fname = "/".join(parts)
if os.path.isfile(fname):
test_files.add(fname)

View file

@ -347,7 +347,7 @@ mock_mqtt_component = threadsafe_coroutine_factory(async_mock_mqtt_component)
def mock_component(hass, component):
"""Mock a component is setup."""
if component in hass.config.components:
AssertionError("Integration {} is already setup".format(component))
AssertionError(f"Integration {component} is already setup")
hass.config.components.add(component)
@ -486,8 +486,8 @@ class MockModule:
partial_manifest=None,
):
"""Initialize the mock module."""
self.__name__ = "homeassistant.components.{}".format(domain)
self.__file__ = "homeassistant/components/{}".format(domain)
self.__name__ = f"homeassistant.components.{domain}"
self.__file__ = f"homeassistant/components/{domain}"
self.DOMAIN = domain
self.DEPENDENCIES = dependencies or []
self.REQUIREMENTS = requirements or []
@ -728,7 +728,7 @@ def patch_yaml_files(files_dict, endswith=True):
return open(fname, encoding="utf-8")
# Not found
raise FileNotFoundError("File not found: {}".format(fname))
raise FileNotFoundError(f"File not found: {fname}")
return patch.object(yaml_loader, "open", mock_open_f, create=True)
@ -791,9 +791,9 @@ def assert_setup_component(count, domain=None):
res = config.get(domain)
res_len = 0 if res is None else len(res)
assert res_len == count, "setup_component failed, expected {} got {}: {}".format(
count, res_len, res
)
assert (
res_len == count
), f"setup_component failed, expected {count} got {res_len}: {res}"
def init_recorder_component(hass, add_config=None):
@ -824,9 +824,7 @@ def mock_restore_cache(hass, states):
)
data.last_states = last_states
_LOGGER.debug("Restore cache: %s", data.last_states)
assert len(data.last_states) == len(states), "Duplicate entity_id? {}".format(
states
)
assert len(data.last_states) == len(states), f"Duplicate entity_id? {states}"
async def get_restore_state_data() -> restore_state.RestoreStateData:
return data
@ -855,7 +853,7 @@ class MockDependency:
base = MagicMock()
to_mock = {
"{}.{}".format(self.root, tom): resolve(base, tom.split("."))
f"{self.root}.{tom}": resolve(base, tom.split("."))
for tom in self.submodules
}
to_mock[self.root] = base
@ -1017,10 +1015,7 @@ async def get_system_health_info(hass, domain):
def mock_integration(hass, module):
"""Mock an integration."""
integration = loader.Integration(
hass,
"homeassistant.components.{}".format(module.DOMAIN),
None,
module.mock_manifest(),
hass, f"homeassistant.components.{module.DOMAIN}", None, module.mock_manifest(),
)
_LOGGER.info("Adding mock integration: %s", module.DOMAIN)
@ -1108,45 +1103,31 @@ class hashdict(dict):
return tuple(sorted(self.items()))
def __repr__(self): # noqa: D105 no docstring
return ", ".join("{0}={1}".format(str(i[0]), repr(i[1])) for i in self.__key())
return ", ".join(f"{i[0]!s}={i[1]!r}" for i in self.__key())
def __hash__(self): # noqa: D105 no docstring
return hash(self.__key())
def __setitem__(self, key, value): # noqa: D105 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def __delitem__(self, key): # noqa: D105 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def clear(self): # noqa: D102 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def pop(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def popitem(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def setdefault(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
def update(self, *args, **kwargs): # noqa: D102 no docstring
raise TypeError(
"{0} does not support item assignment".format(self.__class__.__name__)
)
raise TypeError(f"{self.__class__.__name__} does not support item assignment")
# update is not ok because it mutates the object
# __add__ is ok because it creates a new object

View file

@ -155,7 +155,7 @@ class TestHDDTempSensor(unittest.TestCase):
assert len(self.hass.states.all()) == 1
state = self.hass.states.get("sensor.hd_temperature_dev_sdx1")
assert state.attributes.get("friendly_name") == "HD Temperature " + "/dev/sdx1"
assert state.attributes.get("friendly_name") == "HD Temperature /dev/sdx1"
@patch("telnetlib.Telnet", new=TelnetMock)
def test_hddtemp_multiple_disks(self):

View file

@ -372,7 +372,7 @@ class TestLight(unittest.TestCase):
return StringIO(profile_data)
return real_open(path, *args, **kwargs)
profile_data = "id,x,y,brightness\n" + "group.all_lights.default,.4,.6,99\n"
profile_data = "id,x,y,brightness\ngroup.all_lights.default,.4,.6,99\n"
with mock.patch("os.path.isfile", side_effect=_mock_isfile):
with mock.patch("builtins.open", side_effect=_mock_open):
with mock_storage():

View file

@ -156,12 +156,12 @@ def mock_light(test_features={}, test_state={}, n=0):
mock_light_data = Mock(**test_state)
mock_light = Mock(
id="mock-light-id-{}".format(n),
id=f"mock-light-id-{n}",
reachable=True,
observe=Mock(),
device_info=MagicMock(),
)
mock_light.name = "tradfri_light_{}".format(n)
mock_light.name = f"tradfri_light_{n}"
# Set supported features for the light.
features = {**DEFAULT_TEST_FEATURES, **test_features}
@ -258,7 +258,7 @@ async def test_turn_on(
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": "light.tradfri_light_{}".format(id), **test_data},
{"entity_id": f"light.tradfri_light_{id}", **test_data},
blocking=True,
)
await hass.async_block_till_done()
@ -286,7 +286,7 @@ async def test_turn_on(
await hass.async_block_till_done()
# Check that the state is correct.
states = hass.states.get("light.tradfri_light_{}".format(id))
states = hass.states.get(f"light.tradfri_light_{id}")
for k, v in expected_result.items():
if k == "state":
assert states.state == v
@ -342,7 +342,7 @@ def mock_group(test_state={}, n=0):
state = {**default_state, **test_state}
mock_group = Mock(member_ids=[], observe=Mock(), **state)
mock_group.name = "tradfri_group_{}".format(n)
mock_group.name = f"tradfri_group_{n}"
return mock_group

View file

@ -63,7 +63,7 @@ class TestUkTransportSensor(unittest.TestCase):
bus_state = self.hass.states.get("sensor.next_bus_to_wantage")
assert type(bus_state.state) == str
assert bus_state.name == "Next bus to {}".format(BUS_DIRECTION)
assert bus_state.name == f"Next bus to {BUS_DIRECTION}"
assert bus_state.attributes.get(ATTR_ATCOCODE) == BUS_ATCOCODE
assert bus_state.attributes.get(ATTR_LOCALITY) == "Harwell Campus"
assert bus_state.attributes.get(ATTR_STOP_NAME) == "Bus Station"
@ -85,7 +85,7 @@ class TestUkTransportSensor(unittest.TestCase):
train_state = self.hass.states.get("sensor.next_train_to_WAT")
assert type(train_state.state) == str
assert train_state.name == "Next train to {}".format(TRAIN_DESTINATION_NAME)
assert train_state.name == f"Next train to {TRAIN_DESTINATION_NAME}"
assert train_state.attributes.get(ATTR_STATION_CODE) == TRAIN_STATION_CODE
assert train_state.attributes.get(ATTR_CALLING_AT) == TRAIN_DESTINATION_NAME
assert len(train_state.attributes.get(ATTR_NEXT_TRAINS)) == 25

View file

@ -25,9 +25,7 @@ from homeassistant.setup import async_setup_component
from tests.common import assert_setup_component, load_fixture, mock_component
scanner_path = (
"homeassistant.components.unifi_direct.device_tracker." + "UnifiDeviceScanner"
)
scanner_path = "homeassistant.components.unifi_direct.device_tracker.UnifiDeviceScanner"
@pytest.fixture(autouse=True)

View file

@ -118,14 +118,14 @@ async def test_if_fires_on_state_change(hass, calls):
hass.states.async_set("vacuum.entity", STATE_CLEANING)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "cleaning - device - {} - docked - cleaning".format(
"vacuum.entity"
assert (
calls[0].data["some"] == "cleaning - device - vacuum.entity - docked - cleaning"
)
# Fake that the entity is docked
hass.states.async_set("vacuum.entity", STATE_DOCKED)
await hass.async_block_till_done()
assert len(calls) == 2
assert calls[1].data["some"] == "docked - device - {} - cleaning - docked".format(
"vacuum.entity"
assert (
calls[1].data["some"] == "docked - device - vacuum.entity - cleaning - docked"
)

View file

@ -24,13 +24,13 @@ async def test_unregistering_webhook(hass, mock_client):
hass.components.webhook.async_register("test", "Test hook", webhook_id, handle)
resp = await mock_client.post("/api/webhook/{}".format(webhook_id))
resp = await mock_client.post(f"/api/webhook/{webhook_id}")
assert resp.status == 200
assert len(hooks) == 1
hass.components.webhook.async_unregister(webhook_id)
resp = await mock_client.post("/api/webhook/{}".format(webhook_id))
resp = await mock_client.post(f"/api/webhook/{webhook_id}")
assert resp.status == 200
assert len(hooks) == 1
@ -73,9 +73,7 @@ async def test_posting_webhook_json(hass, mock_client):
hass.components.webhook.async_register("test", "Test hook", webhook_id, handle)
resp = await mock_client.post(
"/api/webhook/{}".format(webhook_id), json={"data": True}
)
resp = await mock_client.post(f"/api/webhook/{webhook_id}", json={"data": True})
assert resp.status == 200
assert len(hooks) == 1
assert hooks[0][0] is hass
@ -94,7 +92,7 @@ async def test_posting_webhook_no_data(hass, mock_client):
hass.components.webhook.async_register("test", "Test hook", webhook_id, handle)
resp = await mock_client.post("/api/webhook/{}".format(webhook_id))
resp = await mock_client.post(f"/api/webhook/{webhook_id}")
assert resp.status == 200
assert len(hooks) == 1
assert hooks[0][0] is hass
@ -114,7 +112,7 @@ async def test_webhook_put(hass, mock_client):
hass.components.webhook.async_register("test", "Test hook", webhook_id, handle)
resp = await mock_client.put("/api/webhook/{}".format(webhook_id))
resp = await mock_client.put(f"/api/webhook/{webhook_id}")
assert resp.status == 200
assert len(hooks) == 1
assert hooks[0][0] is hass
@ -133,7 +131,7 @@ async def test_webhook_head(hass, mock_client):
hass.components.webhook.async_register("test", "Test hook", webhook_id, handle)
resp = await mock_client.head("/api/webhook/{}".format(webhook_id))
resp = await mock_client.head(f"/api/webhook/{webhook_id}")
assert resp.status == 200
assert len(hooks) == 1
assert hooks[0][0] is hass

View file

@ -38,12 +38,11 @@ def assert_state_equals(
entity_id = get_entity_id(measure, profile)
state_obj = hass.states.get(entity_id)
assert state_obj, "Expected entity {} to exist but it did not".format(entity_id)
assert state_obj, f"Expected entity {entity_id} to exist but it did not"
assert state_obj.state == str(
expected
), "Expected {} but was {} for measure {}, {}".format(
expected, state_obj.state, measure, entity_id
assert state_obj.state == str(expected), (
f"Expected {expected} but was {state_obj.state} "
f"for measure {measure}, {entity_id}"
)

View file

@ -174,7 +174,7 @@ async def test_xiaomi_exceptions(hass, caplog, mock_mirobo_errors):
async def test_xiaomi_vacuum_services(hass, caplog, mock_mirobo_is_got_error):
"""Test vacuum supported features."""
entity_name = "test_vacuum_cleaner_1"
entity_id = "{}.{}".format(DOMAIN, entity_name)
entity_id = f"{DOMAIN}.{entity_name}"
await async_setup_component(
hass,
@ -319,7 +319,7 @@ async def test_xiaomi_vacuum_services(hass, caplog, mock_mirobo_is_got_error):
async def test_xiaomi_specific_services(hass, caplog, mock_mirobo_is_on):
"""Test vacuum supported features."""
entity_name = "test_vacuum_cleaner_2"
entity_id = "{}.{}".format(DOMAIN, entity_name)
entity_id = f"{DOMAIN}.{entity_name}"
await async_setup_component(
hass,

View file

@ -129,9 +129,7 @@ async def test_connection_error_on_init(hass, caplog, valid_settings, connection
and record.name == "homeassistant.components.yessssms.notify"
):
assert (
"Connection Error, could not verify login data for '{}'".format(
"educom"
)
"Connection Error, could not verify login data for 'educom'"
in record.message
)
for record in caplog.records:

View file

@ -113,7 +113,7 @@ class YahooWeatherMock:
def getWeatherImage(self, code): # pylint: disable=invalid-name
"""Create a link to weather image from yahoo code."""
return "https://l.yimg.com/a/i/us/we/52/{}.gif".format(code)
return f"https://l.yimg.com/a/i/us/we/52/{code}.gif"
class TestWeather(unittest.TestCase):

View file

@ -18,9 +18,7 @@ def mock_zeroconf():
def service_update_mock(zeroconf, service, handlers):
"""Call service update handler."""
handlers[0](
zeroconf, service, "{}.{}".format("name", service), ServiceStateChange.Added
)
handlers[0](zeroconf, service, f"name.{service}", ServiceStateChange.Added)
def get_service_info_mock(service_type, name):

View file

@ -110,9 +110,9 @@ async def async_build_devices(hass, zha_gateway, config_entry, cluster_ids):
[],
None,
zha_gateway,
ieee="00:15:8d:00:02:32:4f:0{}".format(counter),
manufacturer="Fake{}".format(cluster_id),
model="FakeModel{}".format(cluster_id),
ieee=f"00:15:8d:00:02:32:4f:0{counter}",
manufacturer=f"Fake{cluster_id}",
model=f"FakeModel{cluster_id}",
)
counter += 1

View file

@ -459,18 +459,18 @@ async def test_value_entities(hass, mock_openzwave):
entry = ent_reg.async_get("zwave.mock_node")
assert entry is not None
assert entry.unique_id == "node-{}".format(node.node_id)
assert entry.unique_id == f"node-{node.node_id}"
node_dev_id = entry.device_id
entry = ent_reg.async_get("binary_sensor.mock_node_mock_value")
assert entry is not None
assert entry.unique_id == "{}-{}".format(node.node_id, value.object_id)
assert entry.unique_id == f"{node.node_id}-{value.object_id}"
assert entry.name is None
assert entry.device_id == node_dev_id
entry = ent_reg.async_get("binary_sensor.mock_node_mock_value_b")
assert entry is not None
assert entry.unique_id == "{}-{}".format(node.node_id, value2.object_id)
assert entry.unique_id == f"{node.node_id}-{value2.object_id}"
assert entry.name is None
assert entry.device_id != node_dev_id
device_id_b = entry.device_id
@ -482,7 +482,7 @@ async def test_value_entities(hass, mock_openzwave):
device = dev_reg.async_get(device_id_b)
assert device is not None
assert device.name == "{} ({})".format(node.name, value2.instance)
assert device.name == f"{node.name} ({value2.instance})"
# test renaming without updating
await hass.services.async_call(
@ -510,7 +510,7 @@ async def test_value_entities(hass, mock_openzwave):
device = dev_reg.async_get(device_id_b)
assert device is not None
assert device.name == "{} ({})".format(node.name, value2.instance)
assert device.name == f"{node.name} ({value2.instance})"
# test renaming
await hass.services.async_call(
@ -528,11 +528,11 @@ async def test_value_entities(hass, mock_openzwave):
entry = ent_reg.async_get("zwave.new_node")
assert entry is not None
assert entry.unique_id == "node-{}".format(node.node_id)
assert entry.unique_id == f"node-{node.node_id}"
entry = ent_reg.async_get("binary_sensor.new_node_mock_value")
assert entry is not None
assert entry.unique_id == "{}-{}".format(node.node_id, value.object_id)
assert entry.unique_id == f"{node.node_id}-{value.object_id}"
device = dev_reg.async_get(node_dev_id)
assert device is not None
@ -541,7 +541,7 @@ async def test_value_entities(hass, mock_openzwave):
device = dev_reg.async_get(device_id_b)
assert device is not None
assert device.name == "{} ({})".format(node.name, value2.instance)
assert device.name == f"{node.name} ({value2.instance})"
await hass.services.async_call(
"zwave",
@ -557,7 +557,7 @@ async def test_value_entities(hass, mock_openzwave):
entry = ent_reg.async_get("binary_sensor.new_node_new_label")
assert entry is not None
assert entry.unique_id == "{}-{}".format(node.node_id, value.object_id)
assert entry.unique_id == f"{node.node_id}-{value.object_id}"
async def test_value_discovery_existing_entity(hass, mock_openzwave):

View file

@ -59,9 +59,7 @@ def verify_cleanup():
count = len(INSTANCES)
for inst in INSTANCES:
inst.stop()
pytest.exit(
"Detected non stopped instances ({}), aborting test run".format(count)
)
pytest.exit(f"Detected non stopped instances ({count}), aborting test run")
@pytest.fixture
@ -185,8 +183,7 @@ def hass_client(hass, aiohttp_client, hass_access_token):
async def auth_client():
"""Return an authenticated client."""
return await aiohttp_client(
hass.http.app,
headers={"Authorization": "Bearer {}".format(hass_access_token)},
hass.http.app, headers={"Authorization": f"Bearer {hass_access_token}"},
)
return auth_client

View file

@ -84,7 +84,7 @@ async def test_discovery_single_instance(hass, discovery_flow_conf, source):
flow.context = {}
MockConfigEntry(domain="test").add_to_hass(hass)
result = await getattr(flow, "async_step_{}".format(source))({})
result = await getattr(flow, f"async_step_{source}")({})
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "single_instance_allowed"
@ -97,7 +97,7 @@ async def test_discovery_confirmation(hass, discovery_flow_conf, source):
flow.hass = hass
flow.context = {}
result = await getattr(flow, "async_step_{}".format(source))({})
result = await getattr(flow, f"async_step_{source}")({})
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "confirm"

View file

@ -103,8 +103,8 @@ async def test_setup_recovers_when_setup_raises(hass):
OrderedDict(
[
(DOMAIN, {"platform": "mod1"}),
("{} 2".format(DOMAIN), {"platform": "non_exist"}),
("{} 3".format(DOMAIN), {"platform": "mod2"}),
(f"{DOMAIN} 2", {"platform": "non_exist"}),
(f"{DOMAIN} 3", {"platform": "mod2"}),
]
)
)

View file

@ -541,7 +541,7 @@ async def test_setup_entry(hass):
assert await entity_platform.async_setup_entry(config_entry)
await hass.async_block_till_done()
full_name = "{}.{}".format(entity_platform.domain, config_entry.domain)
full_name = f"{entity_platform.domain}.{config_entry.domain}"
assert full_name in hass.config.components
assert len(hass.states.async_entity_ids()) == 1
assert len(registry.entities) == 1
@ -560,7 +560,7 @@ async def test_setup_entry_platform_not_ready(hass, caplog):
with patch.object(entity_platform, "async_call_later") as mock_call_later:
assert not await ent_platform.async_setup_entry(config_entry)
full_name = "{}.{}".format(ent_platform.domain, config_entry.domain)
full_name = f"{ent_platform.domain}.{config_entry.domain}"
assert full_name not in hass.config.components
assert len(async_setup_entry.mock_calls) == 1
assert "Platform test not ready yet" in caplog.text

View file

@ -62,7 +62,7 @@ async def test_loading_parallel(hass, store, hass_storage, caplog):
assert results[0] is MOCK_DATA
assert results[1] is MOCK_DATA
assert caplog.text.count("Loading data for {}".format(store.key))
assert caplog.text.count(f"Loading data for {store.key}")
async def test_saving_with_delay(hass, store, hass_storage):

View file

@ -19,7 +19,7 @@ def test_temperature_not_a_number(hass):
with pytest.raises(Exception) as exception:
display_temp(hass, temp, TEMP_CELSIUS, PRECISION_HALVES)
assert "Temperature is not a number: {}".format(temp) in str(exception.value)
assert f"Temperature is not a number: {temp}" in str(exception.value)
def test_celsius_halves(hass):

View file

@ -65,7 +65,7 @@ def assert_result_info(info, result, entities=None, domains=None, all_states=Fal
def test_template_equality():
"""Test template comparison and hashing."""
template_one = template.Template("{{ template_one }}")
template_one_1 = template.Template("{{ template_" + "one }}")
template_one_1 = template.Template("{{ template_one }}")
template_two = template.Template("{{ template_two }}")
assert template_one == template_one_1
@ -486,9 +486,9 @@ def test_timestamp_custom(hass):
for inp, fmt, local, out in tests:
if fmt:
fil = "timestamp_custom('{}')".format(fmt)
fil = f"timestamp_custom('{fmt}')"
elif fmt and local:
fil = "timestamp_custom('{0}', {1})".format(fmt, local)
fil = f"timestamp_custom('{fmt}', {local})"
else:
fil = "timestamp_custom"

Some files were not shown because too many files have changed in this diff Show more