Use literal string interpolation in core (f-strings) (#26166)

This commit is contained in:
Franck Nijhof 2019-08-23 18:53:33 +02:00 committed by Paulus Schoutsen
parent 1efa29d6ff
commit decf13b948
67 changed files with 180 additions and 246 deletions

View file

@ -168,7 +168,7 @@ def get_arguments() -> argparse.Namespace:
parser.add_argument(
"--runner",
action="store_true",
help="On restart exit with code {}".format(RESTART_EXIT_CODE),
help=f"On restart exit with code {RESTART_EXIT_CODE}",
)
parser.add_argument(
"--script", nargs=argparse.REMAINDER, help="Run one of the embedded scripts"
@ -240,7 +240,7 @@ def write_pid(pid_file: str) -> None:
with open(pid_file, "w") as file:
file.write(str(pid))
except IOError:
print("Fatal Error: Unable to write pid file {}".format(pid_file))
print(f"Fatal Error: Unable to write pid file {pid_file}")
sys.exit(1)
@ -326,7 +326,7 @@ def try_to_restart() -> None:
thread.is_alive() and not thread.daemon for thread in threading.enumerate()
)
if nthreads > 1:
sys.stderr.write("Found {} non-daemonic threads.\n".format(nthreads))
sys.stderr.write(f"Found {nthreads} non-daemonic threads.\n")
# Somehow we sometimes seem to trigger an assertion in the python threading
# module. It seems we find threads that have no associated OS level thread

View file

@ -278,9 +278,7 @@ class AuthManager:
module = self.get_auth_mfa_module(mfa_module_id)
if module is None:
raise ValueError(
"Unable find multi-factor auth module: {}".format(mfa_module_id)
)
raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
await module.async_setup_user(user.id, data)
@ -295,9 +293,7 @@ class AuthManager:
module = self.get_auth_mfa_module(mfa_module_id)
if module is None:
raise ValueError(
"Unable find multi-factor auth module: {}".format(mfa_module_id)
)
raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
await module.async_depose_user(user.id)
@ -356,7 +352,7 @@ class AuthManager:
):
# Each client_name can only have one
# long_lived_access_token type of refresh token
raise ValueError("{} already exists".format(client_name))
raise ValueError(f"{client_name} already exists")
return await self._store.async_create_refresh_token(
user,

View file

@ -94,7 +94,7 @@ class AuthStore:
for group_id in group_ids or []:
group = self._groups.get(group_id)
if group is None:
raise ValueError("Invalid group specified {}".format(group_id))
raise ValueError(f"Invalid group specified {group_id}")
groups.append(group)
kwargs = {

View file

@ -144,15 +144,13 @@ async def auth_mfa_module_from_config(
async def _load_mfa_module(hass: HomeAssistant, module_name: str) -> types.ModuleType:
"""Load an mfa auth module."""
module_path = "homeassistant.auth.mfa_modules.{}".format(module_name)
module_path = f"homeassistant.auth.mfa_modules.{module_name}"
try:
module = importlib.import_module(module_path)
except ImportError as err:
_LOGGER.error("Unable to load mfa module %s: %s", module_name, err)
raise HomeAssistantError(
"Unable to load mfa module {}: {}".format(module_name, err)
)
raise HomeAssistantError(f"Unable to load mfa module {module_name}: {err}")
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
return module

View file

@ -144,14 +144,10 @@ async def load_auth_provider_module(
) -> types.ModuleType:
"""Load an auth provider."""
try:
module = importlib.import_module(
"homeassistant.auth.providers.{}".format(provider)
)
module = importlib.import_module(f"homeassistant.auth.providers.{provider}")
except ImportError as err:
_LOGGER.error("Unable to load auth provider %s: %s", provider, err)
raise HomeAssistantError(
"Unable to load auth provider {}: {}".format(provider, err)
)
raise HomeAssistantError(f"Unable to load auth provider {provider}: {err}")
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
return module
@ -166,7 +162,7 @@ async def load_auth_provider_module(
# https://github.com/python/mypy/issues/1424
reqs = module.REQUIREMENTS # type: ignore
await requirements.async_process_requirements(
hass, "auth provider {}".format(provider), reqs
hass, f"auth provider {provider}", reqs
)
processed.add(provider)

View file

@ -163,7 +163,7 @@ def async_enable_logging(
# ensure that the handlers it sets up wraps the correct streams.
logging.basicConfig(level=logging.INFO)
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
colorfmt = f"%(log_color)s{fmt}%(reset)s"
logging.getLogger().handlers[0].setFormatter(
ColoredFormatter(
colorfmt,

View file

@ -138,7 +138,7 @@ class APIEventStream(HomeAssistantView):
if payload is stop_obj:
break
msg = "data: {}\n\n".format(payload)
msg = f"data: {payload}\n\n"
_LOGGER.debug("STREAM %s WRITING %s", id(stop_obj), msg.strip())
await response.write(msg.encode("UTF-8"))
except asyncio.TimeoutError:
@ -316,7 +316,7 @@ class APIEventView(HomeAssistantView):
event_type, event_data, ha.EventOrigin.remote, self.context(request)
)
return self.json_message("Event {} fired.".format(event_type))
return self.json_message(f"Event {event_type} fired.")
class APIServicesView(HomeAssistantView):
@ -388,7 +388,7 @@ class APITemplateView(HomeAssistantView):
return tpl.async_render(data.get("variables"))
except (ValueError, TemplateError) as ex:
return self.json_message(
"Error rendering template: {}".format(ex), HTTP_BAD_REQUEST
f"Error rendering template: {ex}", HTTP_BAD_REQUEST
)

View file

@ -143,7 +143,7 @@ async def async_setup(hass, config):
async def turn_onoff_service_handler(service_call):
"""Handle automation turn on/off service calls."""
tasks = []
method = "async_{}".format(service_call.service)
method = f"async_{service_call.service}"
for entity in await component.async_extract_from_service(service_call):
tasks.append(getattr(entity, method)())
@ -378,7 +378,7 @@ async def _async_process_config(hass, config, component):
for list_no, config_block in enumerate(conf):
automation_id = config_block.get(CONF_ID)
name = config_block.get(CONF_ALIAS) or "{} {}".format(config_key, list_no)
name = config_block.get(CONF_ALIAS) or f"{config_key} {list_no}"
hidden = config_block[CONF_HIDE_ENTITY]
initial_state = config_block.get(CONF_INITIAL_STATE)
@ -431,7 +431,7 @@ def _async_get_action(hass, config, name):
await script_obj.async_run(variables, context)
except Exception as err: # pylint: disable=broad-except
script_obj.async_log_exception(
_LOGGER, "Error while executing automation {}".format(entity_id), err
_LOGGER, f"Error while executing automation {entity_id}", err
)
return action

View file

@ -36,7 +36,7 @@ async def async_setup(hass, config):
async def setup_panel(panel_name):
"""Set up a panel."""
panel = importlib.import_module(".{}".format(panel_name), __name__)
panel = importlib.import_module(f".{panel_name}", __name__)
if not panel:
return
@ -44,7 +44,7 @@ async def async_setup(hass, config):
success = await panel.async_setup(hass)
if success:
key = "{}.{}".format(DOMAIN, panel_name)
key = f"{DOMAIN}.{panel_name}"
hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: key})
@callback
@ -82,8 +82,8 @@ class BaseEditConfigView(HomeAssistantView):
post_write_hook=None,
):
"""Initialize a config view."""
self.url = "/api/config/%s/%s/{config_key}" % (component, config_type)
self.name = "api:config:%s:%s" % (component, config_type)
self.url = f"/api/config/{component}/{config_type}/{{config_key}}"
self.name = f"api:config:{component}:{config_type}"
self.path = path
self.key_schema = key_schema
self.data_schema = data_schema
@ -126,14 +126,14 @@ class BaseEditConfigView(HomeAssistantView):
try:
self.key_schema(config_key)
except vol.Invalid as err:
return self.json_message("Key malformed: {}".format(err), 400)
return self.json_message(f"Key malformed: {err}", 400)
try:
# We just validate, we don't store that data because
# we don't want to store the defaults.
self.data_schema(data)
except vol.Invalid as err:
return self.json_message("Message malformed: {}".format(err), 400)
return self.json_message(f"Message malformed: {err}", 400)
hass = request.app["hass"]
path = hass.config.path(self.path)

View file

@ -61,10 +61,10 @@ def async_request_config(
Will return an ID to be used for sequent calls.
"""
if link_name is not None and link_url is not None:
description += "\n\n[{}]({})".format(link_name, link_url)
description += f"\n\n[{link_name}]({link_url})"
if description_image is not None:
description += "\n\n![Description image]({})".format(description_image)
description += f"\n\n![Description image]({description_image})"
instance = hass.data.get(_KEY_INSTANCE)

View file

@ -28,7 +28,7 @@ class DemoCamera(Camera):
self._images_index = (self._images_index + 1) % 4
image_path = os.path.join(
os.path.dirname(__file__), "demo_{}.jpg".format(self._images_index)
os.path.dirname(__file__), f"demo_{self._images_index}.jpg"
)
_LOGGER.debug("Loading camera_image: %s", image_path)
with open(image_path, "rb") as file:

View file

@ -417,7 +417,7 @@ class DemoTVShowPlayer(AbstractDemoPlayer):
@property
def media_title(self):
"""Return the title of current playing media."""
return "Chapter {}".format(self._cur_episode)
return f"Chapter {self._cur_episode}"
@property
def media_series_title(self):

View file

@ -244,7 +244,7 @@ class DemoVacuum(VacuumDevice):
if self.supported_features & SUPPORT_SEND_COMMAND == 0:
return
self._status = "Executing {}({})".format(command, params)
self._status = f"Executing {command}({params})"
self._state = True
self.schedule_update_ha_state()

View file

@ -274,9 +274,7 @@ async def async_setup(hass, config):
("frontend_latest", True),
("frontend_es5", True),
):
hass.http.register_static_path(
"/{}".format(path), str(root_path / path), should_cache
)
hass.http.register_static_path(f"/{path}", str(root_path / path), should_cache)
hass.http.register_static_path(
"/auth/authorize", str(root_path / "authorize.html"), False
@ -294,9 +292,7 @@ async def async_setup(hass, config):
# To smooth transition to new urls, add redirects to new urls of dev tools
# Added June 27, 2019. Can be removed in 2021.
for panel in ("event", "info", "service", "state", "template", "mqtt"):
hass.http.register_redirect(
"/dev-{}".format(panel), "/developer-tools/{}".format(panel)
)
hass.http.register_redirect(f"/dev-{panel}", f"/developer-tools/{panel}")
async_register_built_in_panel(
hass,

View file

@ -271,7 +271,7 @@ async def async_setup(hass, config):
hass.components.persistent_notification.async_create(
"Config error. See dev-info panel for details.",
"Config validating",
"{0}.check_config".format(HASS_DOMAIN),
f"{HASS_DOMAIN}.check_config",
)
return

View file

@ -80,7 +80,7 @@ class HassIO:
This method return a coroutine.
"""
return self.send_command("/addons/{}/info".format(addon), method="get")
return self.send_command(f"/addons/{addon}/info", method="get")
@_api_data
def get_ingress_panels(self):
@ -120,7 +120,7 @@ class HassIO:
This method return a coroutine.
"""
return self.send_command("/discovery/{}".format(uuid), method="get")
return self.send_command(f"/discovery/{uuid}", method="get")
@_api_bool
async def update_hass_api(self, http_config, refresh_token):
@ -156,7 +156,7 @@ class HassIO:
with async_timeout.timeout(timeout):
request = await self.websession.request(
method,
"http://{}{}".format(self._ip, command),
f"http://{self._ip}{command}",
json=payload,
headers={X_HASSIO: os.environ.get("HASSIO_TOKEN", "")},
)

View file

@ -75,7 +75,7 @@ class HassIOView(HomeAssistantView):
method = getattr(self._websession, request.method.lower())
client = await method(
"http://{}/{}".format(self._host, path),
f"http://{self._host}/{path}",
data=data,
headers=headers,
timeout=read_timeout,

View file

@ -42,7 +42,7 @@ class HassIOIngress(HomeAssistantView):
def _create_url(self, token: str, path: str) -> str:
"""Create URL to service."""
return "http://{}/ingress/{}/{}".format(self._host, token, path)
return f"http://{self._host}/ingress/{token}/{path}"
async def _handle(
self, request: web.Request, token: str, path: str
@ -91,7 +91,7 @@ class HassIOIngress(HomeAssistantView):
# Support GET query
if request.query_string:
url = "{}?{}".format(url, request.query_string)
url = f"{url}?{request.query_string}"
# Start proxy
async with self._websession.ws_connect(
@ -175,15 +175,15 @@ def _init_header(
headers[X_HASSIO] = os.environ.get("HASSIO_TOKEN", "")
# Ingress information
headers[X_INGRESS_PATH] = "/api/hassio_ingress/{}".format(token)
headers[X_INGRESS_PATH] = f"/api/hassio_ingress/{token}"
# Set X-Forwarded-For
forward_for = request.headers.get(hdrs.X_FORWARDED_FOR)
connected_ip = ip_address(request.transport.get_extra_info("peername")[0])
if forward_for:
forward_for = "{}, {!s}".format(forward_for, connected_ip)
forward_for = f"{forward_for}, {connected_ip!s}"
else:
forward_for = "{!s}".format(connected_ip)
forward_for = f"{connected_ip!s}"
headers[hdrs.X_FORWARDED_FOR] = forward_for
# Set X-Forwarded-Host

View file

@ -133,12 +133,12 @@ class ApiConfig:
if host.startswith(("http://", "https://")):
self.base_url = host
elif use_ssl:
self.base_url = "https://{}".format(host)
self.base_url = f"https://{host}"
else:
self.base_url = "http://{}".format(host)
self.base_url = f"http://{host}"
if port is not None:
self.base_url += ":{}".format(port)
self.base_url += f":{port}"
async def async_setup(hass, config):
@ -268,15 +268,11 @@ class HomeAssistantHTTP:
if not hasattr(view, "url"):
class_name = view.__class__.__name__
raise AttributeError(
'{0} missing required attribute "url"'.format(class_name)
)
raise AttributeError(f'{class_name} missing required attribute "url"')
if not hasattr(view, "name"):
class_name = view.__class__.__name__
raise AttributeError(
'{0} missing required attribute "name"'.format(class_name)
)
raise AttributeError(f'{class_name} missing required attribute "name"')
view.register(self.app, self.app.router)

View file

@ -127,7 +127,7 @@ async def process_wrong_login(request):
_LOGGER.warning("Banned IP %s for too many login attempts", remote_addr)
hass.components.persistent_notification.async_create(
"Too many login attempts from {}".format(remote_addr),
f"Too many login attempts from {remote_addr}",
"Banning IP address",
NOTIFICATION_ID_BAN,
)

View file

@ -43,9 +43,7 @@ class RequestDataValidator:
kwargs["data"] = self._schema(data)
except vol.Invalid as err:
_LOGGER.error("Data does not match schema: %s", err)
return view.json_message(
"Message format incorrect: {}".format(err), 400
)
return view.json_message(f"Message format incorrect: {err}", 400)
result = await method(view, request, *args, **kwargs)
return result

View file

@ -10,7 +10,7 @@ from aiohttp.web_urldispatcher import StaticResource
# mypy: allow-untyped-defs
CACHE_TIME = 31 * 86400 # = 1 month
CACHE_HEADERS = {hdrs.CACHE_CONTROL: "public, max-age={}".format(CACHE_TIME)}
CACHE_HEADERS = {hdrs.CACHE_CONTROL: f"public, max-age={CACHE_TIME}"}
# https://github.com/PyCQA/astroid/issues/633

View file

@ -49,13 +49,11 @@ def _cv_input_number(cfg):
maximum = cfg.get(CONF_MAX)
if minimum >= maximum:
raise vol.Invalid(
"Maximum ({}) is not greater than minimum ({})".format(minimum, maximum)
f"Maximum ({minimum}) is not greater than minimum ({maximum})"
)
state = cfg.get(CONF_INITIAL)
if state is not None and (state < minimum or state > maximum):
raise vol.Invalid(
"Initial value {} not in range {}-{}".format(state, minimum, maximum)
)
raise vol.Invalid(f"Initial value {state} not in range {minimum}-{maximum}")
return cfg

View file

@ -45,12 +45,12 @@ def _cv_input_text(cfg):
maximum = cfg.get(CONF_MAX)
if minimum > maximum:
raise vol.Invalid(
"Max len ({}) is not greater than min len ({})".format(minimum, maximum)
f"Max len ({minimum}) is not greater than min len ({maximum})"
)
state = cfg.get(CONF_INITIAL)
if state is not None and (len(state) < minimum or len(state) > maximum):
raise vol.Invalid(
"Initial value {} length not in range {}-{}".format(state, minimum, maximum)
f"Initial value {state} length not in range {minimum}-{maximum}"
)
return cfg

View file

@ -94,7 +94,7 @@ class IntegrationSensor(RestoreEntity):
self._state = 0
self._method = integration_method
self._name = name if name is not None else "{} integral".format(source_entity)
self._name = name if name is not None else f"{source_entity} integral"
if unit_of_measurement is None:
self._unit_template = "{}{}{}".format(

View file

@ -55,7 +55,7 @@ async def async_setup(hass, config):
for intent_type, conf in intents.items():
if CONF_ACTION in conf:
conf[CONF_ACTION] = script.Script(
hass, conf[CONF_ACTION], "Intent Script {}".format(intent_type)
hass, conf[CONF_ACTION], f"Intent Script {intent_type}"
)
intent.async_register(hass, ScriptIntentHandler(intent_type, conf))

View file

@ -113,7 +113,7 @@ def discover_scripts(hass):
@bind_hass
def execute_script(hass, name, data=None):
"""Execute a script."""
filename = "{}.py".format(name)
filename = f"{name}.py"
with open(hass.config.path(FOLDER, sanitize_filename(filename))) as fil:
source = fil.read()
execute(hass, filename, source, data)
@ -166,9 +166,7 @@ def execute(hass, filename, source, data=None):
or isinstance(obj, TimeWrapper)
and name not in ALLOWED_TIME
):
raise ScriptError(
"Not allowed to access {}.{}".format(obj.__class__.__name__, name)
)
raise ScriptError(f"Not allowed to access {obj.__class__.__name__}.{name}")
return getattr(obj, name, default)
@ -188,7 +186,7 @@ def execute(hass, filename, source, data=None):
"_iter_unpack_sequence_": guarded_iter_unpack_sequence,
"_unpack_sequence_": guarded_unpack_sequence,
}
logger = logging.getLogger("{}.{}".format(__name__, filename))
logger = logging.getLogger(f"{__name__}.{filename}")
local = {"hass": hass, "data": data or {}, "logger": logger}
try:

View file

@ -107,7 +107,7 @@ def _drop_index(engine, table_name, index_name):
# Engines like DB2/Oracle
try:
engine.execute(text("DROP INDEX {index}".format(index=index_name)))
engine.execute(text(f"DROP INDEX {index_name}"))
except SQLAlchemyError:
pass
else:
@ -170,7 +170,7 @@ def _add_columns(engine, table_name, columns_def):
table_name,
)
columns_def = ["ADD {}".format(col_def) for col_def in columns_def]
columns_def = [f"ADD {col_def}" for col_def in columns_def]
try:
engine.execute(
@ -265,9 +265,7 @@ def _apply_update(engine, new_version, old_version):
# 'context_parent_id CHARACTER(36)',
# ])
else:
raise ValueError(
"No schema migration defined for version {}".format(new_version)
)
raise ValueError(f"No schema migration defined for version {new_version}")
def _inspect_schema_version(engine, session):

View file

@ -209,7 +209,7 @@ class ScriptEntity(ToggleEntity):
await self.script.async_run(kwargs.get(ATTR_VARIABLES), context)
except Exception as err: # pylint: disable=broad-except
self.script.async_log_exception(
_LOGGER, "Error executing script {}".format(self.entity_id), err
_LOGGER, f"Error executing script {self.entity_id}", err
)
raise err

View file

@ -198,7 +198,7 @@ async def async_setup(hass, config):
return
if service.service == "write":
logger = logging.getLogger(
service.data.get(CONF_LOGGER, "{}.external".format(__name__))
service.data.get(CONF_LOGGER, f"{__name__}.external")
)
level = service.data[CONF_LEVEL]
getattr(logger, level)(service.data[CONF_MESSAGE])

View file

@ -165,9 +165,7 @@ async def async_setup(hass, config):
DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True
)
service_name = p_config.get(
CONF_SERVICE_NAME, "{}_{}".format(p_type, SERVICE_SAY)
)
service_name = p_config.get(CONF_SERVICE_NAME, f"{p_type}_{SERVICE_SAY}")
hass.services.async_register(
DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY
)
@ -229,7 +227,7 @@ class SpeechManager:
init_tts_cache_dir, cache_dir
)
except OSError as err:
raise HomeAssistantError("Can't init cache dir {}".format(err))
raise HomeAssistantError(f"Can't init cache dir {err}")
def get_cache_files():
"""Return a dict of given engine files."""
@ -251,7 +249,7 @@ class SpeechManager:
try:
cache_files = await self.hass.async_add_job(get_cache_files)
except OSError as err:
raise HomeAssistantError("Can't read cache dir {}".format(err))
raise HomeAssistantError(f"Can't read cache dir {err}")
if cache_files:
self.file_cache.update(cache_files)
@ -293,7 +291,7 @@ class SpeechManager:
# Languages
language = language or provider.default_language
if language is None or language not in provider.supported_languages:
raise HomeAssistantError("Not supported language {0}".format(language))
raise HomeAssistantError(f"Not supported language {language}")
# Options
if provider.default_options and options:
@ -308,9 +306,7 @@ class SpeechManager:
if opt_name not in (provider.supported_options or [])
]
if invalid_opts:
raise HomeAssistantError(
"Invalid options found: {}".format(invalid_opts)
)
raise HomeAssistantError(f"Invalid options found: {invalid_opts}")
options_key = ctypes.c_size_t(hash(frozenset(options))).value
else:
options_key = "-"
@ -330,7 +326,7 @@ class SpeechManager:
engine, key, message, use_cache, language, options
)
return "{}/api/tts_proxy/{}".format(self.base_url, filename)
return f"{self.base_url}/api/tts_proxy/{filename}"
async def async_get_tts_audio(self, engine, key, message, cache, language, options):
"""Receive TTS and store for view in cache.
@ -341,10 +337,10 @@ class SpeechManager:
extension, data = await provider.async_get_tts_audio(message, language, options)
if data is None or extension is None:
raise HomeAssistantError("No TTS from {} for '{}'".format(engine, message))
raise HomeAssistantError(f"No TTS from {engine} for '{message}'")
# Create file infos
filename = ("{}.{}".format(key, extension)).lower()
filename = (f"{key}.{extension}").lower()
data = self.write_tags(filename, data, provider, message, language, options)
@ -381,7 +377,7 @@ class SpeechManager:
"""
filename = self.file_cache.get(key)
if not filename:
raise HomeAssistantError("Key {} not in file cache!".format(key))
raise HomeAssistantError(f"Key {key} not in file cache!")
voice_file = os.path.join(self.cache_dir, filename)
@ -394,7 +390,7 @@ class SpeechManager:
data = await self.hass.async_add_job(load_speech)
except OSError:
del self.file_cache[key]
raise HomeAssistantError("Can't read {}".format(voice_file))
raise HomeAssistantError(f"Can't read {voice_file}")
self._async_store_to_memcache(key, filename, data)
@ -425,7 +421,7 @@ class SpeechManager:
if key not in self.mem_cache:
if key not in self.file_cache:
raise HomeAssistantError("{} not in cache!".format(key))
raise HomeAssistantError(f"{key} not in cache!")
await self.async_file_to_mem(key)
content, _ = mimetypes.guess_type(filename)

View file

@ -98,7 +98,7 @@ async def async_setup(hass, config):
tariff_confs.append(
{
CONF_METER: meter,
CONF_NAME: "{} {}".format(meter, tariff),
CONF_NAME: f"{meter} {tariff}",
CONF_TARIFF: tariff,
}
)

View file

@ -107,7 +107,7 @@ class UtilityMeterSensor(RestoreEntity):
if name:
self._name = name
else:
self._name = "{} meter".format(source_entity)
self._name = f"{source_entity} meter"
self._unit_of_measurement = None
self._period = meter_type
self._period_offset = meter_offset

View file

@ -33,7 +33,7 @@ CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
def setup(hass, config):
"""Set up Zeroconf and make Home Assistant discoverable."""
zeroconf_name = "{}.{}".format(hass.config.location_name, ZEROCONF_TYPE)
zeroconf_name = f"{hass.config.location_name}.{ZEROCONF_TYPE}"
params = {
"version": __version__,

View file

@ -317,7 +317,7 @@ async def async_hass_config_yaml(hass: HomeAssistant) -> Dict:
path = find_config_file(hass.config.config_dir)
if path is None:
raise HomeAssistantError(
"Config file not found in: {}".format(hass.config.config_dir)
f"Config file not found in: {hass.config.config_dir}"
)
config = load_yaml_config_file(path)
return config
@ -443,7 +443,7 @@ def _format_config_error(ex: vol.Invalid, domain: str, config: Dict) -> str:
This method must be run in the event loop.
"""
message = "Invalid config for [{}]: ".format(domain)
message = f"Invalid config for [{domain}]: "
if "extra keys not allowed" in ex.error_message:
message += (
"[{option}] is an invalid option for [{domain}]. "
@ -705,7 +705,7 @@ async def merge_packages_config(
error = _recursive_merge(conf=config[comp_name], package=comp_conf)
if error:
_log_pkg_error(
pack_name, comp_name, config, "has duplicate key '{}'".format(error)
pack_name, comp_name, config, f"has duplicate key '{error}'"
)
return config
@ -777,7 +777,7 @@ async def async_process_component_config(
p_config
)
except vol.Invalid as ex:
async_log_exception(ex, "{}.{}".format(domain, p_name), p_config, hass)
async_log_exception(ex, f"{domain}.{p_name}", p_config, hass)
continue
platforms.append(p_validated)
@ -836,7 +836,7 @@ def async_notify_setup_error(
else:
part = name
message += " - {}\n".format(part)
message += f" - {part}\n"
message += "\nPlease check your config."

View file

@ -1365,7 +1365,7 @@ class Config:
self.time_zone = time_zone
dt_util.set_default_time_zone(time_zone)
else:
raise ValueError("Received invalid time zone {}".format(time_zone_str))
raise ValueError(f"Received invalid time zone {time_zone_str}")
@callback
def _update(

View file

@ -126,7 +126,7 @@ class FlowManager:
self, flow: Any, step_id: str, user_input: Optional[Dict]
) -> Dict:
"""Handle a step of a flow."""
method = "async_step_{}".format(step_id)
method = f"async_step_{step_id}"
if not hasattr(flow, method):
self._progress.pop(flow.flow_id)

View file

@ -25,7 +25,7 @@ class TemplateError(HomeAssistantError):
def __init__(self, exception: jinja2.TemplateError) -> None:
"""Init the error."""
super().__init__("{}: {}".format(exception.__class__.__name__, exception))
super().__init__(f"{exception.__class__.__name__}: {exception}")
class PlatformNotReady(HomeAssistantError):
@ -73,10 +73,10 @@ class ServiceNotFound(HomeAssistantError):
def __init__(self, domain: str, service: str) -> None:
"""Initialize error."""
super().__init__(self, "Service {}.{} not found".format(domain, service))
super().__init__(self, f"Service {domain}.{service} not found")
self.domain = domain
self.service = service
def __str__(self) -> str:
"""Return string representation."""
return "Unable to find service {}/{}".format(self.domain, self.service)
return f"Unable to find service {self.domain}/{self.service}"

View file

@ -62,7 +62,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
message = "Package {} setup failed. Component {} {}".format(
package, component, message
)
domain = "homeassistant.packages.{}.{}".format(package, component)
domain = f"homeassistant.packages.{package}.{component}"
pack_config = core_config[CONF_PACKAGES].get(package, config)
result.add_error(message, domain, pack_config)
@ -77,9 +77,9 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
return result.add_error("File configuration.yaml not found.")
config = await hass.async_add_executor_job(load_yaml_config_file, config_path)
except FileNotFoundError:
return result.add_error("File not found: {}".format(config_path))
return result.add_error(f"File not found: {config_path}")
except HomeAssistantError as err:
return result.add_error("Error loading {}: {}".format(config_path, err))
return result.add_error(f"Error loading {config_path}: {err}")
finally:
yaml_loader.clear_secret_cache()
@ -106,13 +106,13 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
try:
integration = await async_get_integration_with_requirements(hass, domain)
except (RequirementsNotFound, loader.IntegrationNotFound) as ex:
result.add_error("Component error: {} - {}".format(domain, ex))
result.add_error(f"Component error: {domain} - {ex}")
continue
try:
component = integration.get_component()
except ImportError as ex:
result.add_error("Component error: {} - {}".format(domain, ex))
result.add_error(f"Component error: {domain} - {ex}")
continue
config_schema = getattr(component, "CONFIG_SCHEMA", None)
@ -159,7 +159,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
RequirementsNotFound,
ImportError,
) as ex:
result.add_error("Platform error {}.{} - {}".format(domain, p_name, ex))
result.add_error(f"Platform error {domain}.{p_name} - {ex}")
continue
# Validate platform specific schema
@ -168,7 +168,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
try:
p_validated = platform_schema(p_validated)
except vol.Invalid as ex:
_comp_error(ex, "{}.{}".format(domain, p_name), p_validated)
_comp_error(ex, f"{domain}.{p_name}", p_validated)
continue
platforms.append(p_validated)

View file

@ -243,11 +243,11 @@ class Entity:
This method must be run in the event loop.
"""
if self.hass is None:
raise RuntimeError("Attribute hass is None for {}".format(self))
raise RuntimeError(f"Attribute hass is None for {self}")
if self.entity_id is None:
raise NoEntitySpecifiedError(
"No entity id specified for entity {}".format(self.name)
f"No entity id specified for entity {self.name}"
)
# update entity data
@ -264,11 +264,11 @@ class Entity:
def async_write_ha_state(self):
"""Write the state to the state machine."""
if self.hass is None:
raise RuntimeError("Attribute hass is None for {}".format(self))
raise RuntimeError(f"Attribute hass is None for {self}")
if self.entity_id is None:
raise NoEntitySpecifiedError(
"No entity id specified for entity {}".format(self.name)
f"No entity id specified for entity {self.name}"
)
self._async_write_ha_state()

View file

@ -205,7 +205,7 @@ class EntityComponent:
async def handle_service(call):
"""Handle the service."""
service_name = "{}.{}".format(self.domain, name)
service_name = f"{self.domain}.{name}"
await self.hass.helpers.service.entity_service_call(
self._platforms.values(), func, call, service_name, required_features
)

View file

@ -133,7 +133,7 @@ class EntityPlatform:
current_platform.set(self)
logger = self.logger
hass = self.hass
full_name = "{}.{}".format(self.domain, self.platform_name)
full_name = f"{self.domain}.{self.platform_name}"
logger.info("Setting up %s", full_name)
warn_task = hass.loop.call_later(
@ -357,7 +357,7 @@ class EntityPlatform:
"Not adding entity %s because it's disabled",
entry.name
or entity.name
or '"{} {}"'.format(self.platform_name, entity.unique_id),
or f'"{self.platform_name} {entity.unique_id}"',
)
return
@ -386,12 +386,12 @@ class EntityPlatform:
# Make sure it is valid in case an entity set the value themselves
if not valid_entity_id(entity.entity_id):
raise HomeAssistantError("Invalid entity id: {}".format(entity.entity_id))
raise HomeAssistantError(f"Invalid entity id: {entity.entity_id}")
if (
entity.entity_id in self.entities
or entity.entity_id in self.hass.states.async_entity_ids(self.domain)
):
msg = "Entity id already exists: {}".format(entity.entity_id)
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

View file

@ -166,9 +166,7 @@ class EntityRegistry:
)
entity_id = self.async_generate_entity_id(
domain,
suggested_object_id or "{}_{}".format(platform, unique_id),
known_object_ids,
domain, suggested_object_id or f"{platform}_{unique_id}", known_object_ids
)
if (

View file

@ -58,7 +58,7 @@ async def async_handle(
handler = hass.data.get(DATA_KEY, {}).get(intent_type) # type: IntentHandler
if handler is None:
raise UnknownIntent("Unknown intent {}".format(intent_type))
raise UnknownIntent(f"Unknown intent {intent_type}")
intent = Intent(hass, platform, intent_type, slots or {}, text_input)
@ -68,13 +68,11 @@ async def async_handle(
return result
except vol.Invalid as err:
_LOGGER.warning("Received invalid slot info for %s: %s", intent_type, err)
raise InvalidSlotInfo(
"Received invalid slot info for {}".format(intent_type)
) from err
raise InvalidSlotInfo(f"Received invalid slot info for {intent_type}") from err
except IntentHandleError:
raise
except Exception as err:
raise IntentUnexpectedError("Error handling {}".format(intent_type)) from err
raise IntentUnexpectedError(f"Error handling {intent_type}") from err
class IntentError(HomeAssistantError):
@ -109,7 +107,7 @@ def async_match_state(
state = _fuzzymatch(name, states, lambda state: state.name)
if state is None:
raise IntentHandleError("Unable to find an entity called {}".format(name))
raise IntentHandleError(f"Unable to find an entity called {name}")
return state
@ -118,9 +116,7 @@ def async_match_state(
def async_test_feature(state: State, feature: int, feature_name: str) -> None:
"""Test is state supports a feature."""
if state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) & feature == 0:
raise IntentHandleError(
"Entity {} does not support {}".format(state.name, feature_name)
)
raise IntentHandleError(f"Entity {state.name} does not support {feature_name}")
class IntentHandler:

View file

@ -20,7 +20,7 @@ def display_temp(
# If the temperature is not a number this can cause issues
# with Polymer components, so bail early there.
if not isinstance(temperature, Number):
raise TypeError("Temperature is not a number: {}".format(temperature))
raise TypeError(f"Temperature is not a number: {temperature}")
# type ignore: https://github.com/python/mypy/issues/7207
if temperature_unit != ha_unit: # type: ignore

View file

@ -320,10 +320,10 @@ class AllStates:
"""Return the domain state."""
if "." in name:
if not valid_entity_id(name):
raise TemplateError("Invalid entity ID '{}'".format(name))
raise TemplateError(f"Invalid entity ID '{name}'")
return _get_state(self._hass, name)
if not valid_entity_id(name + ".entity"):
raise TemplateError("Invalid domain name '{}'".format(name))
raise TemplateError(f"Invalid domain name '{name}'")
return DomainStates(self._hass, name)
def _collect_all(self):
@ -367,9 +367,9 @@ class DomainStates:
def __getattr__(self, name):
"""Return the states."""
entity_id = "{}.{}".format(self._domain, name)
entity_id = f"{self._domain}.{name}"
if not valid_entity_id(entity_id):
raise TemplateError("Invalid entity ID '{}'".format(entity_id))
raise TemplateError(f"Invalid entity ID '{entity_id}'")
return _get_state(self._hass, entity_id)
def _collect_domain(self):
@ -399,7 +399,7 @@ class DomainStates:
def __repr__(self):
"""Representation of Domain States."""
return "<template DomainStates('{}')>".format(self._domain)
return f"<template DomainStates('{self._domain}')>"
class TemplateState(State):
@ -426,7 +426,7 @@ class TemplateState(State):
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
if unit is None:
return state.state
return "{} {}".format(state.state, unit)
return f"{state.state} {unit}"
def __getattribute__(self, name):
"""Return an attribute of the state."""

View file

@ -20,9 +20,9 @@ def recursive_flatten(prefix: Any, data: Dict) -> Dict[str, Any]:
output = {}
for key, value in data.items():
if isinstance(value, dict):
output.update(recursive_flatten("{}{}.".format(prefix, key), value))
output.update(recursive_flatten(f"{prefix}{key}.", value))
else:
output["{}{}".format(prefix, key)] = value
output[f"{prefix}{key}"] = value
return output
@ -60,7 +60,7 @@ async def component_translation_file(
if integration.file_path.name != domain:
return None
filename = "{}.json".format(language)
filename = f"{language}.json"
return str(integration.file_path / ".translations" / filename)

View file

@ -165,10 +165,7 @@ class Integration:
continue
return cls(
hass,
"{}.{}".format(root_module.__name__, domain),
manifest_path.parent,
manifest,
hass, f"{root_module.__name__}.{domain}", manifest_path.parent, manifest
)
return None
@ -229,16 +226,16 @@ class Integration:
def get_platform(self, platform_name: str) -> ModuleType:
"""Return a platform for an integration."""
cache = self.hass.data.setdefault(DATA_COMPONENTS, {})
full_name = "{}.{}".format(self.domain, platform_name)
full_name = f"{self.domain}.{platform_name}"
if full_name not in cache:
cache[full_name] = importlib.import_module(
"{}.{}".format(self.pkg_path, platform_name)
f"{self.pkg_path}.{platform_name}"
)
return cache[full_name] # type: ignore
def __repr__(self) -> str:
"""Text representation of class."""
return "<Integration {}: {}>".format(self.domain, self.pkg_path)
return f"<Integration {self.domain}: {self.pkg_path}>"
async def async_get_integration(hass: "HomeAssistant", domain: str) -> Integration:
@ -312,7 +309,7 @@ class IntegrationNotFound(LoaderError):
def __init__(self, domain: str) -> None:
"""Initialize a component not found error."""
super().__init__("Integration {} not found.".format(domain))
super().__init__(f"Integration {domain} not found.")
self.domain = domain
@ -321,9 +318,7 @@ class CircularDependency(LoaderError):
def __init__(self, from_domain: str, to_domain: str) -> None:
"""Initialize circular dependency error."""
super().__init__(
"Circular dependency detected: {} -> {}.".format(from_domain, to_domain)
)
super().__init__(f"Circular dependency detected: {from_domain} -> {to_domain}.")
self.from_domain = from_domain
self.to_domain = to_domain
@ -350,7 +345,7 @@ def _load_file(
return None
cache = hass.data[DATA_COMPONENTS] = {}
for path in ("{}.{}".format(base, comp_or_platform) for base in base_paths):
for path in (f"{base}.{comp_or_platform}" for base in base_paths):
try:
module = importlib.import_module(path)
@ -439,7 +434,7 @@ class Components:
component = _load_file(self._hass, comp_name, LOOKUP_PATHS)
if component is None:
raise ImportError("Unable to load {}".format(comp_name))
raise ImportError(f"Unable to load {comp_name}")
wrapped = ModuleWrapper(self._hass, component)
setattr(self, comp_name, wrapped)
@ -457,7 +452,7 @@ class Helpers:
def __getattr__(self, helper_name: str) -> ModuleWrapper:
"""Fetch a helper."""
helper = importlib.import_module("homeassistant.helpers.{}".format(helper_name))
helper = importlib.import_module(f"homeassistant.helpers.{helper_name}")
wrapped = ModuleWrapper(self._hass, helper)
setattr(self, helper_name, wrapped)
return wrapped

View file

@ -22,9 +22,7 @@ class RequirementsNotFound(HomeAssistantError):
def __init__(self, domain: str, requirements: List) -> None:
"""Initialize a component not found error."""
super().__init__(
"Requirements for {} not found: {}.".format(domain, requirements)
)
super().__init__(f"Requirements for {domain} not found: {requirements}.")
self.domain = domain
self.requirements = requirements

View file

@ -39,7 +39,7 @@ def run(args):
hass = core.HomeAssistant(loop)
hass.async_stop_track_tasks()
runtime = loop.run_until_complete(bench(hass))
print("Benchmark {} done in {}s".format(bench.__name__, runtime))
print(f"Benchmark {bench.__name__} done in {runtime}s")
loop.run_until_complete(hass.async_stop())
loop.close()

View file

@ -58,20 +58,18 @@ def run(args):
if args.value:
the_secret = args.value
else:
the_secret = getpass.getpass(
"Please enter the secret for {}: ".format(args.name)
)
the_secret = getpass.getpass(f"Please enter the secret for {args.name}: ")
current_version = credstash.getHighestVersion(args.name, table=table)
credstash.putSecret(
args.name, the_secret, version=int(current_version) + 1, table=table
)
print("Secret {} put successfully".format(args.name))
print(f"Secret {args.name} put successfully")
elif args.action == "get":
the_secret = credstash.getSecret(args.name, table=table)
if the_secret is None:
print("Secret {} not found".format(args.name))
print(f"Secret {args.name} not found")
else:
print("Secret {}={}".format(args.name, the_secret))
print(f"Secret {args.name}={the_secret}")
elif args.action == "del":
credstash.deleteSecrets(args.name, table=table)
print("Deleted secret {}".format(args.name))
print(f"Deleted secret {args.name}")

View file

@ -36,29 +36,27 @@ def run(args):
if args.action == "info":
keyr = keyring.get_keyring()
print("Keyring version {}\n".format(REQUIREMENTS[0].split("==")[1]))
print("Active keyring : {}".format(keyr.__module__))
print(f"Active keyring : {keyr.__module__}")
config_name = os.path.join(platform.config_root(), "keyringrc.cfg")
print("Config location : {}".format(config_name))
print(f"Config location : {config_name}")
print("Data location : {}\n".format(platform.data_root()))
elif args.name is None:
parser.print_help()
return 1
if args.action == "set":
entered_secret = getpass.getpass(
"Please enter the secret for {}: ".format(args.name)
)
entered_secret = getpass.getpass(f"Please enter the secret for {args.name}: ")
keyring.set_password(_SECRET_NAMESPACE, args.name, entered_secret)
print("Secret {} set successfully".format(args.name))
print(f"Secret {args.name} set successfully")
elif args.action == "get":
the_secret = keyring.get_password(_SECRET_NAMESPACE, args.name)
if the_secret is None:
print("Secret {} not found".format(args.name))
print(f"Secret {args.name} not found")
else:
print("Secret {}={}".format(args.name, the_secret))
print(f"Secret {args.name}={the_secret}")
elif args.action == "del":
try:
keyring.delete_password(_SECRET_NAMESPACE, args.name)
print("Deleted secret {}".format(args.name))
print(f"Deleted secret {args.name}")
except keyring.errors.PasswordDeleteError:
print("Secret {} not found".format(args.name))
print(f"Secret {args.name} not found")

View file

@ -240,7 +240,7 @@ async def async_prepare_setup_platform(
try:
platform = integration.get_platform(domain)
except ImportError as exc:
log_error("Platform not found ({}).".format(exc))
log_error(f"Platform not found ({exc}).")
return None
# Already loaded
@ -253,7 +253,7 @@ async def async_prepare_setup_platform(
try:
component = integration.get_component()
except ImportError as exc:
log_error("Unable to import the component ({}).".format(exc))
log_error(f"Unable to import the component ({exc}).")
return None
if hasattr(component, "setup") or hasattr(component, "async_setup"):

View file

@ -86,7 +86,7 @@ def ensure_unique_string(
while test_string in current_strings_set:
tries += 1
test_string = "{}_{}".format(preferred_string, tries)
test_string = f"{preferred_string}_{tries}"
return test_string

View file

@ -25,7 +25,7 @@ def convert(value: float, unit_1: str, unit_2: str) -> float:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_2, LENGTH))
if not isinstance(value, Number):
raise TypeError("{} is not of numeric type".format(value))
raise TypeError(f"{value} is not of numeric type")
# type ignore: https://github.com/python/mypy/issues/7207
if unit_1 == unit_2 or unit_1 not in VALID_UNITS: # type: ignore

View file

@ -193,8 +193,8 @@ def get_age(date: dt.datetime) -> str:
def formatn(number: int, unit: str) -> str:
"""Add "unit" if it's plural."""
if number == 1:
return "1 {}".format(unit)
return "{:d} {}s".format(number, unit)
return f"1 {unit}"
return f"{number:d} {unit}s"
def q_n_r(first: int, second: int) -> Tuple[int, int]:
"""Return quotient and remaining."""

View file

@ -34,7 +34,7 @@ def convert(value: float, unit_1: str, unit_2: str) -> float:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_2, PRESSURE))
if not isinstance(value, Number):
raise TypeError("{} is not of numeric type".format(value))
raise TypeError(f"{value} is not of numeric type")
# type ignore: https://github.com/python/mypy/issues/7207
if unit_1 == unit_2 or unit_1 not in VALID_UNITS: # type: ignore

View file

@ -34,7 +34,7 @@ def convert(volume: float, from_unit: str, to_unit: str) -> float:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, VOLUME))
if not isinstance(volume, Number):
raise TypeError("{} is not of numeric type".format(volume))
raise TypeError(f"{volume} is not of numeric type")
# type ignore: https://github.com/python/mypy/issues/7207
if from_unit == to_unit: # type: ignore

View file

@ -207,7 +207,7 @@ def _ordered_dict(loader: SafeLineLoader, node: yaml.nodes.MappingNode) -> Order
except TypeError:
fname = getattr(loader.stream, "name", "")
raise yaml.MarkedYAMLError(
context='invalid key: "{}"'.format(key),
context=f'invalid key: "{key}"',
context_mark=yaml.Mark(fname, 0, line, -1, None, None),
)
@ -314,7 +314,7 @@ def secret_yaml(loader: SafeLineLoader, node: yaml.nodes.Node) -> JSON_TYPE:
# Catch if package installed and no config
credstash = None
raise HomeAssistantError("Secret {} not defined".format(node.value))
raise HomeAssistantError(f"Secret {node.value} not defined")
yaml.SafeLoader.add_constructor("!include", _include_yaml)

View file

@ -230,9 +230,7 @@ def gather_recursive_requirements(domain, seen=None):
seen = set()
seen.add(domain)
integration = Integration(
pathlib.Path("homeassistant/components/{}".format(domain))
)
integration = Integration(pathlib.Path(f"homeassistant/components/{domain}"))
integration.load_manifest()
reqs = set(integration.manifest["requirements"])
for dep_domain in integration.manifest["dependencies"]:
@ -272,13 +270,13 @@ def gather_requirements_from_manifests(errors, reqs):
integration = integrations[domain]
if not integration.manifest:
errors.append("The manifest for integration {} is invalid.".format(domain))
errors.append(f"The manifest for integration {domain} is invalid.")
continue
process_requirements(
errors,
integration.manifest["requirements"],
"homeassistant.components.{}".format(domain),
f"homeassistant.components.{domain}",
reqs,
)
@ -306,13 +304,9 @@ def process_requirements(errors, module_requirements, package, reqs):
if req in IGNORE_REQ:
continue
if "://" in req:
errors.append(
"{}[Only pypi dependencies are allowed: {}]".format(package, req)
)
errors.append(f"{package}[Only pypi dependencies are allowed: {req}]")
if req.partition("==")[1] == "" and req not in IGNORE_PIN:
errors.append(
"{}[Please pin requirement {}, see {}]".format(package, req, URL_PIN)
)
errors.append(f"{package}[Please pin requirement {req}, see {URL_PIN}]")
reqs.setdefault(req, []).append(package)
@ -321,12 +315,12 @@ def generate_requirements_list(reqs):
output = []
for pkg, requirements in sorted(reqs.items(), key=lambda item: item[0]):
for req in sorted(requirements):
output.append("\n# {}".format(req))
output.append(f"\n# {req}")
if comment_requirement(pkg):
output.append("\n# {}\n".format(pkg))
output.append(f"\n# {pkg}\n")
else:
output.append("\n{}\n".format(pkg))
output.append(f"\n{pkg}\n")
return "".join(output)

View file

@ -68,7 +68,7 @@ def main():
print()
for integration in sorted(invalid_itg, key=lambda itg: itg.domain):
print("Integration {}:".format(integration.domain))
print(f"Integration {integration.domain}:")
for error in integration.errors:
print("*", error)
print()

View file

@ -67,5 +67,5 @@ def validate(integrations: Dict[str, Integration], config):
for dep in integration.manifest["dependencies"]:
if dep not in integrations:
integration.add_error(
"dependencies", "Dependency {} does not exist".format(dep)
"dependencies", f"Dependency {dep} does not exist"
)

View file

@ -79,20 +79,20 @@ class Integration:
"""Load manifest."""
manifest_path = self.path / "manifest.json"
if not manifest_path.is_file():
self.add_error("model", "Manifest file {} not found".format(manifest_path))
self.add_error("model", f"Manifest file {manifest_path} not found")
return
try:
manifest = json.loads(manifest_path.read_text())
except ValueError as err:
self.add_error("model", "Manifest contains invalid JSON: {}".format(err))
self.add_error("model", f"Manifest contains invalid JSON: {err}")
return
self.manifest = manifest
def import_pkg(self, platform=None):
"""Import the Python file."""
pkg = "homeassistant.components.{}".format(self.domain)
pkg = f"homeassistant.components.{self.domain}"
if platform is not None:
pkg += ".{}".format(platform)
pkg += f".{platform}"
return importlib.import_module(pkg)

View file

@ -34,7 +34,7 @@ def printc(the_color, *args):
print(escape_codes[the_color] + msg + escape_codes["reset"])
except KeyError:
print(msg)
raise ValueError("Invalid color {}".format(the_color))
raise ValueError(f"Invalid color {the_color}")
def validate_requirements_ok():
@ -145,7 +145,7 @@ async def lint(files):
lint_ok = True
for err in res:
err_msg = "{} {}:{} {}".format(err.file, err.line, err.col, err.msg)
err_msg = f"{err.file} {err.line}:{err.col} {err.msg}"
# tests/* does not have to pass lint
if err.skip:

View file

@ -40,18 +40,11 @@ def get_component_path(lang, component):
"""Get the component translation path."""
if os.path.isdir(os.path.join("homeassistant", "components", component)):
return os.path.join(
"homeassistant",
"components",
component,
".translations",
"{}.json".format(lang),
"homeassistant", "components", component, ".translations", f"{lang}.json"
)
else:
return os.path.join(
"homeassistant",
"components",
".translations",
"{}.{}.json".format(component, lang),
"homeassistant", "components", ".translations", f"{component}.{lang}.json"
)
@ -64,7 +57,7 @@ def get_platform_path(lang, component, platform):
component,
platform,
".translations",
"{}.json".format(lang),
f"{lang}.json",
)
else:
return os.path.join(
@ -72,7 +65,7 @@ def get_platform_path(lang, component, platform):
"components",
component,
".translations",
"{}.{}.json".format(platform, lang),
f"{platform}.{lang}.json",
)

View file

@ -35,7 +35,7 @@ def save_json(filename: str, data: Union[List, Dict]):
def find_strings_files():
"""Return the paths of the strings source files."""
return itertools.chain(
glob.iglob("strings*.json"), glob.iglob("*{}strings*.json".format(os.sep))
glob.iglob("strings*.json"), glob.iglob(f"*{os.sep}strings*.json")
)

View file

@ -81,7 +81,7 @@ def bump_version(version, bump_type):
to_change["pre"] = ("b", 0)
else:
assert False, "Unsupported type: {}".format(bump_type)
assert False, f"Unsupported type: {bump_type}"
temp = Version("0")
temp._version = version._version._replace(**to_change)
@ -95,15 +95,9 @@ def write_version(version):
major, minor, patch = str(version).split(".", 2)
content = re.sub(
"MAJOR_VERSION = .*\n", "MAJOR_VERSION = {}\n".format(major), content
)
content = re.sub(
"MINOR_VERSION = .*\n", "MINOR_VERSION = {}\n".format(minor), content
)
content = re.sub(
"PATCH_VERSION = .*\n", "PATCH_VERSION = '{}'\n".format(patch), content
)
content = re.sub("MAJOR_VERSION = .*\n", f"MAJOR_VERSION = {major}\n", content)
content = re.sub("MINOR_VERSION = .*\n", f"MINOR_VERSION = {minor}\n", content)
content = re.sub("PATCH_VERSION = .*\n", f"PATCH_VERSION = '{patch}'\n", content)
with open("homeassistant/const.py", "wt") as fil:
content = fil.write(content)
@ -129,7 +123,7 @@ def main():
if not arguments.commit:
return
subprocess.run(["git", "commit", "-am", "Bumped version to {}".format(bumped)])
subprocess.run(["git", "commit", "-am", f"Bumped version to {bumped}"])
def test_bump_version():