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( parser.add_argument(
"--runner", "--runner",
action="store_true", 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( parser.add_argument(
"--script", nargs=argparse.REMAINDER, help="Run one of the embedded scripts" "--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: with open(pid_file, "w") as file:
file.write(str(pid)) file.write(str(pid))
except IOError: 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) sys.exit(1)
@ -326,7 +326,7 @@ def try_to_restart() -> None:
thread.is_alive() and not thread.daemon for thread in threading.enumerate() thread.is_alive() and not thread.daemon for thread in threading.enumerate()
) )
if nthreads > 1: 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 # 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 # 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) module = self.get_auth_mfa_module(mfa_module_id)
if module is None: if module is None:
raise ValueError( raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
"Unable find multi-factor auth module: {}".format(mfa_module_id)
)
await module.async_setup_user(user.id, data) await module.async_setup_user(user.id, data)
@ -295,9 +293,7 @@ class AuthManager:
module = self.get_auth_mfa_module(mfa_module_id) module = self.get_auth_mfa_module(mfa_module_id)
if module is None: if module is None:
raise ValueError( raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
"Unable find multi-factor auth module: {}".format(mfa_module_id)
)
await module.async_depose_user(user.id) await module.async_depose_user(user.id)
@ -356,7 +352,7 @@ class AuthManager:
): ):
# Each client_name can only have one # Each client_name can only have one
# long_lived_access_token type of refresh token # 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( return await self._store.async_create_refresh_token(
user, user,

View file

@ -94,7 +94,7 @@ class AuthStore:
for group_id in group_ids or []: for group_id in group_ids or []:
group = self._groups.get(group_id) group = self._groups.get(group_id)
if group is None: if group is None:
raise ValueError("Invalid group specified {}".format(group_id)) raise ValueError(f"Invalid group specified {group_id}")
groups.append(group) groups.append(group)
kwargs = { 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: async def _load_mfa_module(hass: HomeAssistant, module_name: str) -> types.ModuleType:
"""Load an mfa auth module.""" """Load an mfa auth module."""
module_path = "homeassistant.auth.mfa_modules.{}".format(module_name) module_path = f"homeassistant.auth.mfa_modules.{module_name}"
try: try:
module = importlib.import_module(module_path) module = importlib.import_module(module_path)
except ImportError as err: except ImportError as err:
_LOGGER.error("Unable to load mfa module %s: %s", module_name, err) _LOGGER.error("Unable to load mfa module %s: %s", module_name, err)
raise HomeAssistantError( raise HomeAssistantError(f"Unable to load mfa module {module_name}: {err}")
"Unable to load mfa module {}: {}".format(module_name, err)
)
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"): if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
return module return module

View file

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

View file

@ -163,7 +163,7 @@ def async_enable_logging(
# ensure that the handlers it sets up wraps the correct streams. # ensure that the handlers it sets up wraps the correct streams.
logging.basicConfig(level=logging.INFO) 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( logging.getLogger().handlers[0].setFormatter(
ColoredFormatter( ColoredFormatter(
colorfmt, colorfmt,

View file

@ -138,7 +138,7 @@ class APIEventStream(HomeAssistantView):
if payload is stop_obj: if payload is stop_obj:
break break
msg = "data: {}\n\n".format(payload) msg = f"data: {payload}\n\n"
_LOGGER.debug("STREAM %s WRITING %s", id(stop_obj), msg.strip()) _LOGGER.debug("STREAM %s WRITING %s", id(stop_obj), msg.strip())
await response.write(msg.encode("UTF-8")) await response.write(msg.encode("UTF-8"))
except asyncio.TimeoutError: except asyncio.TimeoutError:
@ -316,7 +316,7 @@ class APIEventView(HomeAssistantView):
event_type, event_data, ha.EventOrigin.remote, self.context(request) 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): class APIServicesView(HomeAssistantView):
@ -388,7 +388,7 @@ class APITemplateView(HomeAssistantView):
return tpl.async_render(data.get("variables")) return tpl.async_render(data.get("variables"))
except (ValueError, TemplateError) as ex: except (ValueError, TemplateError) as ex:
return self.json_message( 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): async def turn_onoff_service_handler(service_call):
"""Handle automation turn on/off service calls.""" """Handle automation turn on/off service calls."""
tasks = [] tasks = []
method = "async_{}".format(service_call.service) method = f"async_{service_call.service}"
for entity in await component.async_extract_from_service(service_call): for entity in await component.async_extract_from_service(service_call):
tasks.append(getattr(entity, method)()) 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): for list_no, config_block in enumerate(conf):
automation_id = config_block.get(CONF_ID) 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] hidden = config_block[CONF_HIDE_ENTITY]
initial_state = config_block.get(CONF_INITIAL_STATE) 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) await script_obj.async_run(variables, context)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
script_obj.async_log_exception( 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 return action

View file

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

View file

@ -28,7 +28,7 @@ class DemoCamera(Camera):
self._images_index = (self._images_index + 1) % 4 self._images_index = (self._images_index + 1) % 4
image_path = os.path.join( 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) _LOGGER.debug("Loading camera_image: %s", image_path)
with open(image_path, "rb") as file: with open(image_path, "rb") as file:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -133,12 +133,12 @@ class ApiConfig:
if host.startswith(("http://", "https://")): if host.startswith(("http://", "https://")):
self.base_url = host self.base_url = host
elif use_ssl: elif use_ssl:
self.base_url = "https://{}".format(host) self.base_url = f"https://{host}"
else: else:
self.base_url = "http://{}".format(host) self.base_url = f"http://{host}"
if port is not None: if port is not None:
self.base_url += ":{}".format(port) self.base_url += f":{port}"
async def async_setup(hass, config): async def async_setup(hass, config):
@ -268,15 +268,11 @@ class HomeAssistantHTTP:
if not hasattr(view, "url"): if not hasattr(view, "url"):
class_name = view.__class__.__name__ class_name = view.__class__.__name__
raise AttributeError( raise AttributeError(f'{class_name} missing required attribute "url"')
'{0} missing required attribute "url"'.format(class_name)
)
if not hasattr(view, "name"): if not hasattr(view, "name"):
class_name = view.__class__.__name__ class_name = view.__class__.__name__
raise AttributeError( raise AttributeError(f'{class_name} missing required attribute "name"')
'{0} missing required attribute "name"'.format(class_name)
)
view.register(self.app, self.app.router) 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) _LOGGER.warning("Banned IP %s for too many login attempts", remote_addr)
hass.components.persistent_notification.async_create( 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", "Banning IP address",
NOTIFICATION_ID_BAN, NOTIFICATION_ID_BAN,
) )

View file

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

View file

@ -10,7 +10,7 @@ from aiohttp.web_urldispatcher import StaticResource
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
CACHE_TIME = 31 * 86400 # = 1 month 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 # https://github.com/PyCQA/astroid/issues/633

View file

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

View file

@ -45,12 +45,12 @@ def _cv_input_text(cfg):
maximum = cfg.get(CONF_MAX) maximum = cfg.get(CONF_MAX)
if minimum > maximum: if minimum > maximum:
raise vol.Invalid( 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) state = cfg.get(CONF_INITIAL)
if state is not None and (len(state) < minimum or len(state) > maximum): if state is not None and (len(state) < minimum or len(state) > maximum):
raise vol.Invalid( 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 return cfg

View file

@ -94,7 +94,7 @@ class IntegrationSensor(RestoreEntity):
self._state = 0 self._state = 0
self._method = integration_method 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: if unit_of_measurement is None:
self._unit_template = "{}{}{}".format( self._unit_template = "{}{}{}".format(

View file

@ -55,7 +55,7 @@ async def async_setup(hass, config):
for intent_type, conf in intents.items(): for intent_type, conf in intents.items():
if CONF_ACTION in conf: if CONF_ACTION in conf:
conf[CONF_ACTION] = script.Script( 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)) intent.async_register(hass, ScriptIntentHandler(intent_type, conf))

View file

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

View file

@ -107,7 +107,7 @@ def _drop_index(engine, table_name, index_name):
# Engines like DB2/Oracle # Engines like DB2/Oracle
try: try:
engine.execute(text("DROP INDEX {index}".format(index=index_name))) engine.execute(text(f"DROP INDEX {index_name}"))
except SQLAlchemyError: except SQLAlchemyError:
pass pass
else: else:
@ -170,7 +170,7 @@ def _add_columns(engine, table_name, columns_def):
table_name, 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: try:
engine.execute( engine.execute(
@ -265,9 +265,7 @@ def _apply_update(engine, new_version, old_version):
# 'context_parent_id CHARACTER(36)', # 'context_parent_id CHARACTER(36)',
# ]) # ])
else: else:
raise ValueError( raise ValueError(f"No schema migration defined for version {new_version}")
"No schema migration defined for version {}".format(new_version)
)
def _inspect_schema_version(engine, session): 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) await self.script.async_run(kwargs.get(ATTR_VARIABLES), context)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
self.script.async_log_exception( 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 raise err

View file

@ -198,7 +198,7 @@ async def async_setup(hass, config):
return return
if service.service == "write": if service.service == "write":
logger = logging.getLogger( logger = logging.getLogger(
service.data.get(CONF_LOGGER, "{}.external".format(__name__)) service.data.get(CONF_LOGGER, f"{__name__}.external")
) )
level = service.data[CONF_LEVEL] level = service.data[CONF_LEVEL]
getattr(logger, level)(service.data[CONF_MESSAGE]) 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 DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True
) )
service_name = p_config.get( service_name = p_config.get(CONF_SERVICE_NAME, f"{p_type}_{SERVICE_SAY}")
CONF_SERVICE_NAME, "{}_{}".format(p_type, SERVICE_SAY)
)
hass.services.async_register( hass.services.async_register(
DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY
) )
@ -229,7 +227,7 @@ class SpeechManager:
init_tts_cache_dir, cache_dir init_tts_cache_dir, cache_dir
) )
except OSError as err: 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(): def get_cache_files():
"""Return a dict of given engine files.""" """Return a dict of given engine files."""
@ -251,7 +249,7 @@ class SpeechManager:
try: try:
cache_files = await self.hass.async_add_job(get_cache_files) cache_files = await self.hass.async_add_job(get_cache_files)
except OSError as err: 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: if cache_files:
self.file_cache.update(cache_files) self.file_cache.update(cache_files)
@ -293,7 +291,7 @@ class SpeechManager:
# Languages # Languages
language = language or provider.default_language language = language or provider.default_language
if language is None or language not in provider.supported_languages: 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 # Options
if provider.default_options and options: if provider.default_options and options:
@ -308,9 +306,7 @@ class SpeechManager:
if opt_name not in (provider.supported_options or []) if opt_name not in (provider.supported_options or [])
] ]
if invalid_opts: if invalid_opts:
raise HomeAssistantError( raise HomeAssistantError(f"Invalid options found: {invalid_opts}")
"Invalid options found: {}".format(invalid_opts)
)
options_key = ctypes.c_size_t(hash(frozenset(options))).value options_key = ctypes.c_size_t(hash(frozenset(options))).value
else: else:
options_key = "-" options_key = "-"
@ -330,7 +326,7 @@ class SpeechManager:
engine, key, message, use_cache, language, options 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): async def async_get_tts_audio(self, engine, key, message, cache, language, options):
"""Receive TTS and store for view in cache. """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) extension, data = await provider.async_get_tts_audio(message, language, options)
if data is None or extension is None: 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 # Create file infos
filename = ("{}.{}".format(key, extension)).lower() filename = (f"{key}.{extension}").lower()
data = self.write_tags(filename, data, provider, message, language, options) data = self.write_tags(filename, data, provider, message, language, options)
@ -381,7 +377,7 @@ class SpeechManager:
""" """
filename = self.file_cache.get(key) filename = self.file_cache.get(key)
if not filename: 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) voice_file = os.path.join(self.cache_dir, filename)
@ -394,7 +390,7 @@ class SpeechManager:
data = await self.hass.async_add_job(load_speech) data = await self.hass.async_add_job(load_speech)
except OSError: except OSError:
del self.file_cache[key] 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) 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.mem_cache:
if key not in self.file_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) await self.async_file_to_mem(key)
content, _ = mimetypes.guess_type(filename) content, _ = mimetypes.guess_type(filename)

View file

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

View file

@ -107,7 +107,7 @@ class UtilityMeterSensor(RestoreEntity):
if name: if name:
self._name = name self._name = name
else: else:
self._name = "{} meter".format(source_entity) self._name = f"{source_entity} meter"
self._unit_of_measurement = None self._unit_of_measurement = None
self._period = meter_type self._period = meter_type
self._period_offset = meter_offset 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): def setup(hass, config):
"""Set up Zeroconf and make Home Assistant discoverable.""" """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 = { params = {
"version": __version__, "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) path = find_config_file(hass.config.config_dir)
if path is None: if path is None:
raise HomeAssistantError( 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) config = load_yaml_config_file(path)
return config 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. 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: if "extra keys not allowed" in ex.error_message:
message += ( message += (
"[{option}] is an invalid option for [{domain}]. " "[{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) error = _recursive_merge(conf=config[comp_name], package=comp_conf)
if error: if error:
_log_pkg_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 return config
@ -777,7 +777,7 @@ async def async_process_component_config(
p_config p_config
) )
except vol.Invalid as ex: 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 continue
platforms.append(p_validated) platforms.append(p_validated)
@ -836,7 +836,7 @@ def async_notify_setup_error(
else: else:
part = name part = name
message += " - {}\n".format(part) message += f" - {part}\n"
message += "\nPlease check your config." message += "\nPlease check your config."

View file

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

View file

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

View file

@ -25,7 +25,7 @@ class TemplateError(HomeAssistantError):
def __init__(self, exception: jinja2.TemplateError) -> None: def __init__(self, exception: jinja2.TemplateError) -> None:
"""Init the error.""" """Init the error."""
super().__init__("{}: {}".format(exception.__class__.__name__, exception)) super().__init__(f"{exception.__class__.__name__}: {exception}")
class PlatformNotReady(HomeAssistantError): class PlatformNotReady(HomeAssistantError):
@ -73,10 +73,10 @@ class ServiceNotFound(HomeAssistantError):
def __init__(self, domain: str, service: str) -> None: def __init__(self, domain: str, service: str) -> None:
"""Initialize error.""" """Initialize error."""
super().__init__(self, "Service {}.{} not found".format(domain, service)) super().__init__(self, f"Service {domain}.{service} not found")
self.domain = domain self.domain = domain
self.service = service self.service = service
def __str__(self) -> str: def __str__(self) -> str:
"""Return string representation.""" """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( message = "Package {} setup failed. Component {} {}".format(
package, component, message package, component, message
) )
domain = "homeassistant.packages.{}.{}".format(package, component) domain = f"homeassistant.packages.{package}.{component}"
pack_config = core_config[CONF_PACKAGES].get(package, config) pack_config = core_config[CONF_PACKAGES].get(package, config)
result.add_error(message, domain, pack_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.") return result.add_error("File configuration.yaml not found.")
config = await hass.async_add_executor_job(load_yaml_config_file, config_path) config = await hass.async_add_executor_job(load_yaml_config_file, config_path)
except FileNotFoundError: 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: 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: finally:
yaml_loader.clear_secret_cache() yaml_loader.clear_secret_cache()
@ -106,13 +106,13 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
try: try:
integration = await async_get_integration_with_requirements(hass, domain) integration = await async_get_integration_with_requirements(hass, domain)
except (RequirementsNotFound, loader.IntegrationNotFound) as ex: except (RequirementsNotFound, loader.IntegrationNotFound) as ex:
result.add_error("Component error: {} - {}".format(domain, ex)) result.add_error(f"Component error: {domain} - {ex}")
continue continue
try: try:
component = integration.get_component() component = integration.get_component()
except ImportError as ex: except ImportError as ex:
result.add_error("Component error: {} - {}".format(domain, ex)) result.add_error(f"Component error: {domain} - {ex}")
continue continue
config_schema = getattr(component, "CONFIG_SCHEMA", None) config_schema = getattr(component, "CONFIG_SCHEMA", None)
@ -159,7 +159,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
RequirementsNotFound, RequirementsNotFound,
ImportError, ImportError,
) as ex: ) as ex:
result.add_error("Platform error {}.{} - {}".format(domain, p_name, ex)) result.add_error(f"Platform error {domain}.{p_name} - {ex}")
continue continue
# Validate platform specific schema # Validate platform specific schema
@ -168,7 +168,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> HomeAssistantConfig
try: try:
p_validated = platform_schema(p_validated) p_validated = platform_schema(p_validated)
except vol.Invalid as ex: except vol.Invalid as ex:
_comp_error(ex, "{}.{}".format(domain, p_name), p_validated) _comp_error(ex, f"{domain}.{p_name}", p_validated)
continue continue
platforms.append(p_validated) platforms.append(p_validated)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,7 @@ def display_temp(
# If the temperature is not a number this can cause issues # If the temperature is not a number this can cause issues
# with Polymer components, so bail early there. # with Polymer components, so bail early there.
if not isinstance(temperature, Number): 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 # type ignore: https://github.com/python/mypy/issues/7207
if temperature_unit != ha_unit: # type: ignore if temperature_unit != ha_unit: # type: ignore

View file

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

View file

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

View file

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

View file

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

View file

@ -39,7 +39,7 @@ def run(args):
hass = core.HomeAssistant(loop) hass = core.HomeAssistant(loop)
hass.async_stop_track_tasks() hass.async_stop_track_tasks()
runtime = loop.run_until_complete(bench(hass)) 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.run_until_complete(hass.async_stop())
loop.close() loop.close()

View file

@ -58,20 +58,18 @@ def run(args):
if args.value: if args.value:
the_secret = args.value the_secret = args.value
else: else:
the_secret = getpass.getpass( the_secret = getpass.getpass(f"Please enter the secret for {args.name}: ")
"Please enter the secret for {}: ".format(args.name)
)
current_version = credstash.getHighestVersion(args.name, table=table) current_version = credstash.getHighestVersion(args.name, table=table)
credstash.putSecret( credstash.putSecret(
args.name, the_secret, version=int(current_version) + 1, table=table 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": elif args.action == "get":
the_secret = credstash.getSecret(args.name, table=table) the_secret = credstash.getSecret(args.name, table=table)
if the_secret is None: if the_secret is None:
print("Secret {} not found".format(args.name)) print(f"Secret {args.name} not found")
else: else:
print("Secret {}={}".format(args.name, the_secret)) print(f"Secret {args.name}={the_secret}")
elif args.action == "del": elif args.action == "del":
credstash.deleteSecrets(args.name, table=table) 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": if args.action == "info":
keyr = keyring.get_keyring() keyr = keyring.get_keyring()
print("Keyring version {}\n".format(REQUIREMENTS[0].split("==")[1])) 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") 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())) print("Data location : {}\n".format(platform.data_root()))
elif args.name is None: elif args.name is None:
parser.print_help() parser.print_help()
return 1 return 1
if args.action == "set": if args.action == "set":
entered_secret = getpass.getpass( entered_secret = getpass.getpass(f"Please enter the secret for {args.name}: ")
"Please enter the secret for {}: ".format(args.name)
)
keyring.set_password(_SECRET_NAMESPACE, args.name, entered_secret) 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": elif args.action == "get":
the_secret = keyring.get_password(_SECRET_NAMESPACE, args.name) the_secret = keyring.get_password(_SECRET_NAMESPACE, args.name)
if the_secret is None: if the_secret is None:
print("Secret {} not found".format(args.name)) print(f"Secret {args.name} not found")
else: else:
print("Secret {}={}".format(args.name, the_secret)) print(f"Secret {args.name}={the_secret}")
elif args.action == "del": elif args.action == "del":
try: try:
keyring.delete_password(_SECRET_NAMESPACE, args.name) keyring.delete_password(_SECRET_NAMESPACE, args.name)
print("Deleted secret {}".format(args.name)) print(f"Deleted secret {args.name}")
except keyring.errors.PasswordDeleteError: 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: try:
platform = integration.get_platform(domain) platform = integration.get_platform(domain)
except ImportError as exc: except ImportError as exc:
log_error("Platform not found ({}).".format(exc)) log_error(f"Platform not found ({exc}).")
return None return None
# Already loaded # Already loaded
@ -253,7 +253,7 @@ async def async_prepare_setup_platform(
try: try:
component = integration.get_component() component = integration.get_component()
except ImportError as exc: except ImportError as exc:
log_error("Unable to import the component ({}).".format(exc)) log_error(f"Unable to import the component ({exc}).")
return None return None
if hasattr(component, "setup") or hasattr(component, "async_setup"): 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: while test_string in current_strings_set:
tries += 1 tries += 1
test_string = "{}_{}".format(preferred_string, tries) test_string = f"{preferred_string}_{tries}"
return test_string 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)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_2, LENGTH))
if not isinstance(value, Number): 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 # type ignore: https://github.com/python/mypy/issues/7207
if unit_1 == unit_2 or unit_1 not in VALID_UNITS: # type: ignore 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: def formatn(number: int, unit: str) -> str:
"""Add "unit" if it's plural.""" """Add "unit" if it's plural."""
if number == 1: if number == 1:
return "1 {}".format(unit) return f"1 {unit}"
return "{:d} {}s".format(number, unit) return f"{number:d} {unit}s"
def q_n_r(first: int, second: int) -> Tuple[int, int]: def q_n_r(first: int, second: int) -> Tuple[int, int]:
"""Return quotient and remaining.""" """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)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_2, PRESSURE))
if not isinstance(value, Number): 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 # type ignore: https://github.com/python/mypy/issues/7207
if unit_1 == unit_2 or unit_1 not in VALID_UNITS: # type: ignore 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)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, VOLUME))
if not isinstance(volume, Number): 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 # type ignore: https://github.com/python/mypy/issues/7207
if from_unit == to_unit: # type: ignore 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: except TypeError:
fname = getattr(loader.stream, "name", "") fname = getattr(loader.stream, "name", "")
raise yaml.MarkedYAMLError( raise yaml.MarkedYAMLError(
context='invalid key: "{}"'.format(key), context=f'invalid key: "{key}"',
context_mark=yaml.Mark(fname, 0, line, -1, None, None), 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 # Catch if package installed and no config
credstash = None 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) yaml.SafeLoader.add_constructor("!include", _include_yaml)

View file

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

View file

@ -68,7 +68,7 @@ def main():
print() print()
for integration in sorted(invalid_itg, key=lambda itg: itg.domain): 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: for error in integration.errors:
print("*", error) print("*", error)
print() print()

View file

@ -67,5 +67,5 @@ def validate(integrations: Dict[str, Integration], config):
for dep in integration.manifest["dependencies"]: for dep in integration.manifest["dependencies"]:
if dep not in integrations: if dep not in integrations:
integration.add_error( 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.""" """Load manifest."""
manifest_path = self.path / "manifest.json" manifest_path = self.path / "manifest.json"
if not manifest_path.is_file(): 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 return
try: try:
manifest = json.loads(manifest_path.read_text()) manifest = json.loads(manifest_path.read_text())
except ValueError as err: 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 return
self.manifest = manifest self.manifest = manifest
def import_pkg(self, platform=None): def import_pkg(self, platform=None):
"""Import the Python file.""" """Import the Python file."""
pkg = "homeassistant.components.{}".format(self.domain) pkg = f"homeassistant.components.{self.domain}"
if platform is not None: if platform is not None:
pkg += ".{}".format(platform) pkg += f".{platform}"
return importlib.import_module(pkg) 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"]) print(escape_codes[the_color] + msg + escape_codes["reset"])
except KeyError: except KeyError:
print(msg) print(msg)
raise ValueError("Invalid color {}".format(the_color)) raise ValueError(f"Invalid color {the_color}")
def validate_requirements_ok(): def validate_requirements_ok():
@ -145,7 +145,7 @@ async def lint(files):
lint_ok = True lint_ok = True
for err in res: 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 # tests/* does not have to pass lint
if err.skip: if err.skip:

View file

@ -40,18 +40,11 @@ def get_component_path(lang, component):
"""Get the component translation path.""" """Get the component translation path."""
if os.path.isdir(os.path.join("homeassistant", "components", component)): if os.path.isdir(os.path.join("homeassistant", "components", component)):
return os.path.join( return os.path.join(
"homeassistant", "homeassistant", "components", component, ".translations", f"{lang}.json"
"components",
component,
".translations",
"{}.json".format(lang),
) )
else: else:
return os.path.join( return os.path.join(
"homeassistant", "homeassistant", "components", ".translations", f"{component}.{lang}.json"
"components",
".translations",
"{}.{}.json".format(component, lang),
) )
@ -64,7 +57,7 @@ def get_platform_path(lang, component, platform):
component, component,
platform, platform,
".translations", ".translations",
"{}.json".format(lang), f"{lang}.json",
) )
else: else:
return os.path.join( return os.path.join(
@ -72,7 +65,7 @@ def get_platform_path(lang, component, platform):
"components", "components",
component, component,
".translations", ".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(): def find_strings_files():
"""Return the paths of the strings source files.""" """Return the paths of the strings source files."""
return itertools.chain( 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) to_change["pre"] = ("b", 0)
else: else:
assert False, "Unsupported type: {}".format(bump_type) assert False, f"Unsupported type: {bump_type}"
temp = Version("0") temp = Version("0")
temp._version = version._version._replace(**to_change) temp._version = version._version._replace(**to_change)
@ -95,15 +95,9 @@ def write_version(version):
major, minor, patch = str(version).split(".", 2) major, minor, patch = str(version).split(".", 2)
content = re.sub( content = re.sub("MAJOR_VERSION = .*\n", f"MAJOR_VERSION = {major}\n", content)
"MAJOR_VERSION = .*\n", "MAJOR_VERSION = {}\n".format(major), 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)
content = re.sub(
"MINOR_VERSION = .*\n", "MINOR_VERSION = {}\n".format(minor), content
)
content = re.sub(
"PATCH_VERSION = .*\n", "PATCH_VERSION = '{}'\n".format(patch), content
)
with open("homeassistant/const.py", "wt") as fil: with open("homeassistant/const.py", "wt") as fil:
content = fil.write(content) content = fil.write(content)
@ -129,7 +123,7 @@ def main():
if not arguments.commit: if not arguments.commit:
return 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(): def test_bump_version():