Improve string formatting v5 (#33697)
* Improve string formatting v5 * Address review commentspull/33705/head
parent
39336d3ea3
commit
fca90a8ddc
docs/source
homeassistant
components
aftership
august
calendar
canary
cisco_webex_teams
cloud
coinbase
ezviz
hdmi_cec
nest
websocket_api
wink
withings
wunderground
xiaomi
xiaomi_aqara
zwave
helpers
scripts
util
|
@ -8,19 +8,19 @@ Loosely based on https://github.com/astropy/astropy/pull/347
|
|||
import os
|
||||
import warnings
|
||||
|
||||
__licence__ = 'BSD (3 clause)'
|
||||
__licence__ = "BSD (3 clause)"
|
||||
|
||||
|
||||
def get_github_url(app, view, path):
|
||||
github_fmt = 'https://github.com/{}/{}/{}/{}{}'
|
||||
return (
|
||||
github_fmt.format(app.config.edit_on_github_project, view,
|
||||
app.config.edit_on_github_branch,
|
||||
app.config.edit_on_github_src_path, path))
|
||||
f"https://github.com/{app.config.edit_on_github_project}/"
|
||||
f"{view}/{app.config.edit_on_github_branch}/"
|
||||
f"{app.config.edit_on_github_src_path}{path}"
|
||||
)
|
||||
|
||||
|
||||
def html_page_context(app, pagename, templatename, context, doctree):
|
||||
if templatename != 'page.html':
|
||||
if templatename != "page.html":
|
||||
return
|
||||
|
||||
if not app.config.edit_on_github_project:
|
||||
|
@ -29,16 +29,16 @@ def html_page_context(app, pagename, templatename, context, doctree):
|
|||
if not doctree:
|
||||
warnings.warn("doctree is None")
|
||||
return
|
||||
path = os.path.relpath(doctree.get('source'), app.builder.srcdir)
|
||||
show_url = get_github_url(app, 'blob', path)
|
||||
edit_url = get_github_url(app, 'edit', path)
|
||||
path = os.path.relpath(doctree.get("source"), app.builder.srcdir)
|
||||
show_url = get_github_url(app, "blob", path)
|
||||
edit_url = get_github_url(app, "edit", path)
|
||||
|
||||
context['show_on_github_url'] = show_url
|
||||
context['edit_on_github_url'] = edit_url
|
||||
context["show_on_github_url"] = show_url
|
||||
context["edit_on_github_url"] = edit_url
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('edit_on_github_project', '', True)
|
||||
app.add_config_value('edit_on_github_branch', 'master', True)
|
||||
app.add_config_value('edit_on_github_src_path', '', True) # 'eg' "docs/"
|
||||
app.connect('html-page-context', html_page_context)
|
||||
app.add_config_value("edit_on_github_project", "", True)
|
||||
app.add_config_value("edit_on_github_branch", "master", True)
|
||||
app.add_config_value("edit_on_github_src_path", "", True) # 'eg' "docs/"
|
||||
app.connect("html-page-context", html_page_context)
|
||||
|
|
|
@ -22,25 +22,26 @@ import sys
|
|||
|
||||
from homeassistant.const import __short_version__, __version__
|
||||
|
||||
PROJECT_NAME = 'Home Assistant'
|
||||
PROJECT_PACKAGE_NAME = 'homeassistant'
|
||||
PROJECT_AUTHOR = 'The Home Assistant Authors'
|
||||
PROJECT_COPYRIGHT = f' 2013-2020, {PROJECT_AUTHOR}'
|
||||
PROJECT_LONG_DESCRIPTION = ('Home Assistant is an open-source '
|
||||
'home automation platform running on Python 3. '
|
||||
'Track and control all devices at home and '
|
||||
'automate control. '
|
||||
'Installation in less than a minute.')
|
||||
PROJECT_GITHUB_USERNAME = 'home-assistant'
|
||||
PROJECT_GITHUB_REPOSITORY = 'home-assistant'
|
||||
PROJECT_NAME = "Home Assistant"
|
||||
PROJECT_PACKAGE_NAME = "homeassistant"
|
||||
PROJECT_AUTHOR = "The Home Assistant Authors"
|
||||
PROJECT_COPYRIGHT = f" 2013-2020, {PROJECT_AUTHOR}"
|
||||
PROJECT_LONG_DESCRIPTION = (
|
||||
"Home Assistant is an open-source "
|
||||
"home automation platform running on Python 3. "
|
||||
"Track and control all devices at home and "
|
||||
"automate control. "
|
||||
"Installation in less than a minute."
|
||||
)
|
||||
PROJECT_GITHUB_USERNAME = "home-assistant"
|
||||
PROJECT_GITHUB_REPOSITORY = "home-assistant"
|
||||
|
||||
GITHUB_PATH = '{}/{}'.format(
|
||||
PROJECT_GITHUB_USERNAME, PROJECT_GITHUB_REPOSITORY)
|
||||
GITHUB_URL = f'https://github.com/{GITHUB_PATH}'
|
||||
GITHUB_PATH = f"{PROJECT_GITHUB_USERNAME}/{PROJECT_GITHUB_REPOSITORY}"
|
||||
GITHUB_URL = f"https://github.com/{GITHUB_PATH}"
|
||||
|
||||
|
||||
sys.path.insert(0, os.path.abspath('_ext'))
|
||||
sys.path.insert(0, os.path.abspath('../homeassistant'))
|
||||
sys.path.insert(0, os.path.abspath("_ext"))
|
||||
sys.path.insert(0, os.path.abspath("../homeassistant"))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
|
@ -52,27 +53,27 @@ sys.path.insert(0, os.path.abspath('../homeassistant'))
|
|||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.linkcode',
|
||||
'sphinx_autodoc_annotation',
|
||||
'edit_on_github'
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.linkcode",
|
||||
"sphinx_autodoc_annotation",
|
||||
"edit_on_github",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
#
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = PROJECT_NAME
|
||||
|
@ -88,25 +89,25 @@ version = __short_version__
|
|||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
|
||||
code_branch = 'dev' if 'dev' in __version__ else 'master'
|
||||
code_branch = "dev" if "dev" in __version__ else "master"
|
||||
|
||||
# Edit on Github config
|
||||
edit_on_github_project = GITHUB_PATH
|
||||
edit_on_github_branch = code_branch
|
||||
edit_on_github_src_path = 'docs/source/'
|
||||
edit_on_github_src_path = "docs/source/"
|
||||
|
||||
|
||||
def linkcode_resolve(domain, info):
|
||||
"""Determine the URL corresponding to Python object."""
|
||||
if domain != 'py':
|
||||
if domain != "py":
|
||||
return None
|
||||
modname = info['module']
|
||||
fullname = info['fullname']
|
||||
modname = info["module"]
|
||||
fullname = info["fullname"]
|
||||
submod = sys.modules.get(modname)
|
||||
if submod is None:
|
||||
return None
|
||||
obj = submod
|
||||
for part in fullname.split('.'):
|
||||
for part in fullname.split("."):
|
||||
try:
|
||||
obj = getattr(obj, part)
|
||||
except:
|
||||
|
@ -131,7 +132,8 @@ def linkcode_resolve(domain, info):
|
|||
|
||||
fn = fn[index:]
|
||||
|
||||
return f'{GITHUB_URL}/blob/{code_branch}/{fn}{linespec}'
|
||||
return f"{GITHUB_URL}/blob/{code_branch}/{fn}{linespec}"
|
||||
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -174,7 +176,7 @@ exclude_patterns = []
|
|||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
@ -191,22 +193,22 @@ todo_include_todos = False
|
|||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
html_theme = "alabaster"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
html_theme_options = {
|
||||
'logo': 'logo.png',
|
||||
'logo_name': PROJECT_NAME,
|
||||
'description': PROJECT_LONG_DESCRIPTION,
|
||||
'github_user': PROJECT_GITHUB_USERNAME,
|
||||
'github_repo': PROJECT_GITHUB_REPOSITORY,
|
||||
'github_type': 'star',
|
||||
'github_banner': True,
|
||||
'travis_button': True,
|
||||
'touch_icon': 'logo-apple.png',
|
||||
"logo": "logo.png",
|
||||
"logo_name": PROJECT_NAME,
|
||||
"description": PROJECT_LONG_DESCRIPTION,
|
||||
"github_user": PROJECT_GITHUB_USERNAME,
|
||||
"github_repo": PROJECT_GITHUB_REPOSITORY,
|
||||
"github_type": "star",
|
||||
"github_banner": True,
|
||||
"travis_button": True,
|
||||
"touch_icon": "logo-apple.png",
|
||||
# 'fixed_sidebar': True, # Re-enable when we have more content
|
||||
}
|
||||
|
||||
|
@ -232,12 +234,12 @@ html_theme_options = {
|
|||
# This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#
|
||||
html_favicon = '_static/favicon.ico'
|
||||
html_favicon = "_static/favicon.ico"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
|
@ -249,7 +251,7 @@ html_static_path = ['_static']
|
|||
# bottom, using the given strftime format.
|
||||
# The empty string is equivalent to '%b %d, %Y'.
|
||||
#
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
html_last_updated_fmt = "%b %d, %Y"
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
|
@ -259,13 +261,13 @@ html_use_smartypants = True
|
|||
# Custom sidebar templates, maps document names to template names.
|
||||
#
|
||||
html_sidebars = {
|
||||
'**': [
|
||||
'about.html',
|
||||
'links.html',
|
||||
'searchbox.html',
|
||||
'sourcelink.html',
|
||||
'navigation.html',
|
||||
'relations.html'
|
||||
"**": [
|
||||
"about.html",
|
||||
"links.html",
|
||||
"searchbox.html",
|
||||
"sourcelink.html",
|
||||
"navigation.html",
|
||||
"relations.html",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -326,34 +328,36 @@ html_sidebars = {
|
|||
# html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Home-Assistantdoc'
|
||||
htmlhelp_basename = "Home-Assistantdoc"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'home-assistant.tex', 'Home Assistant Documentation',
|
||||
'Home Assistant Team', 'manual'),
|
||||
(
|
||||
master_doc,
|
||||
"home-assistant.tex",
|
||||
"Home Assistant Documentation",
|
||||
"Home Assistant Team",
|
||||
"manual",
|
||||
)
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -394,8 +398,7 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'home-assistant', 'Home Assistant Documentation',
|
||||
[author], 1)
|
||||
(master_doc, "home-assistant", "Home Assistant Documentation", [author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
|
@ -409,9 +412,15 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'Home-Assistant', 'Home Assistant Documentation',
|
||||
author, 'Home Assistant', 'Open-source home automation platform.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"Home-Assistant",
|
||||
"Home Assistant Documentation",
|
||||
author,
|
||||
"Home Assistant",
|
||||
"Open-source home automation platform.",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
|
|
|
@ -36,9 +36,8 @@ def validate_python() -> None:
|
|||
"""Validate that the right Python version is running."""
|
||||
if sys.version_info[:3] < REQUIRED_PYTHON_VER:
|
||||
print(
|
||||
"Home Assistant requires at least Python {}.{}.{}".format(
|
||||
*REQUIRED_PYTHON_VER
|
||||
)
|
||||
"Home Assistant requires at least Python "
|
||||
f"{REQUIRED_PYTHON_VER[0]}.{REQUIRED_PYTHON_VER[1]}.{REQUIRED_PYTHON_VER[2]}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -191,9 +191,7 @@ class AfterShipSensor(Entity):
|
|||
"name": name,
|
||||
"tracking_number": track["tracking_number"],
|
||||
"slug": track["slug"],
|
||||
"link": "{}{}/{}".format(
|
||||
BASE, track["slug"], track["tracking_number"]
|
||||
),
|
||||
"link": f"{BASE}{track['slug']}/{track['tracking_number']}",
|
||||
"last_update": track["updated_at"],
|
||||
"expected_delivery": track["expected_delivery"],
|
||||
"status": track["tag"],
|
||||
|
|
|
@ -90,8 +90,11 @@ async def async_request_validation(hass, config_entry, august_gateway):
|
|||
hass.data[DOMAIN][entry_id][TWO_FA_REVALIDATE] = configurator.async_request_config(
|
||||
f"{DEFAULT_NAME} ({username})",
|
||||
async_august_configuration_validation_callback,
|
||||
description="August must be re-verified. Please check your {} ({}) and enter the verification "
|
||||
"code below".format(login_method, username),
|
||||
description=(
|
||||
"August must be re-verified. "
|
||||
f"Please check your {login_method} ({username}) "
|
||||
"and enter the verification code below"
|
||||
),
|
||||
submit_caption="Verify",
|
||||
fields=[
|
||||
{"id": VERIFICATION_CODE_KEY, "name": "Verification code", "type": "string"}
|
||||
|
@ -265,7 +268,7 @@ class AugustData(AugustSubscriberMixin):
|
|||
self._api.async_get_doorbell_detail,
|
||||
)
|
||||
_LOGGER.debug(
|
||||
"async_signal_device_id_update (from detail updates): %s", device_id,
|
||||
"async_signal_device_id_update (from detail updates): %s", device_id
|
||||
)
|
||||
self.async_signal_device_id_update(device_id)
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ def calculate_offset(event, offset):
|
|||
time = search.group(1)
|
||||
if ":" not in time:
|
||||
if time[0] == "+" or time[0] == "-":
|
||||
time = "{}0:{}".format(time[0], time[1:])
|
||||
time = f"{time[0]}0:{time[1:]}"
|
||||
else:
|
||||
time = f"0:{time}"
|
||||
|
||||
|
|
|
@ -49,9 +49,7 @@ def setup(hass, config):
|
|||
except (ConnectTimeout, HTTPError) as ex:
|
||||
_LOGGER.error("Unable to connect to Canary service: %s", str(ex))
|
||||
hass.components.persistent_notification.create(
|
||||
"Error: {}<br />"
|
||||
"You will need to restart hass after fixing."
|
||||
"".format(ex),
|
||||
f"Error: {ex}<br />You will need to restart hass after fixing.",
|
||||
title=NOTIFICATION_TITLE,
|
||||
notification_id=NOTIFICATION_ID,
|
||||
)
|
||||
|
|
|
@ -76,7 +76,7 @@ class CanarySensor(Entity):
|
|||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique ID of this sensor."""
|
||||
return "{}_{}".format(self._device_id, self._sensor_type[0])
|
||||
return f"{self._device_id}_{self._sensor_type[0]}"
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
|
|
|
@ -48,7 +48,7 @@ class CiscoWebexTeamsNotificationService(BaseNotificationService):
|
|||
|
||||
title = ""
|
||||
if kwargs.get(ATTR_TITLE) is not None:
|
||||
title = "{}{}".format(kwargs.get(ATTR_TITLE), "<br>")
|
||||
title = f"{kwargs.get(ATTR_TITLE)}<br>"
|
||||
|
||||
try:
|
||||
self.client.messages.create(roomId=self.room, html=f"{title}{message}")
|
||||
|
|
|
@ -119,9 +119,9 @@ class AlexaConfig(alexa_config.AbstractConfig):
|
|||
if self.should_report_state:
|
||||
await self._prefs.async_update(alexa_report_state=False)
|
||||
self.hass.components.persistent_notification.async_create(
|
||||
"There was an error reporting state to Alexa ({}). "
|
||||
f"There was an error reporting state to Alexa ({body['reason']}). "
|
||||
"Please re-link your Alexa skill via the Alexa app to "
|
||||
"continue using it.".format(body["reason"]),
|
||||
"continue using it.",
|
||||
"Alexa state reporting disabled",
|
||||
"cloud_alexa_report",
|
||||
)
|
||||
|
|
|
@ -82,7 +82,7 @@ class AccountSensor(Entity):
|
|||
"""Get the latest state of the sensor."""
|
||||
self._coinbase_data.update()
|
||||
for account in self._coinbase_data.accounts["data"]:
|
||||
if self._name == "Coinbase {}".format(account["name"]):
|
||||
if self._name == f"Coinbase {account['name']}":
|
||||
self._state = account["balance"]["amount"]
|
||||
self._native_balance = account["native_balance"]["amount"]
|
||||
self._native_currency = account["native_balance"]["currency"]
|
||||
|
|
|
@ -219,15 +219,16 @@ class HassEzvizCamera(Camera):
|
|||
ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)
|
||||
|
||||
image = await asyncio.shield(
|
||||
ffmpeg.get_image(self._rtsp_stream, output_format=IMAGE_JPEG,)
|
||||
ffmpeg.get_image(self._rtsp_stream, output_format=IMAGE_JPEG)
|
||||
)
|
||||
return image
|
||||
|
||||
async def stream_source(self):
|
||||
"""Return the stream source."""
|
||||
if self._local_rtsp_port:
|
||||
rtsp_stream_source = "rtsp://{}:{}@{}:{}".format(
|
||||
self._username, self._password, self._local_ip, self._local_rtsp_port
|
||||
rtsp_stream_source = (
|
||||
f"rtsp://{self._username}:{self._password}@"
|
||||
f"{self._local_ip}:{self._local_rtsp_port}"
|
||||
)
|
||||
_LOGGER.debug(
|
||||
"Camera %s source stream: %s", self._serial, rtsp_stream_source
|
||||
|
|
|
@ -67,9 +67,7 @@ class CecPlayerDevice(CecDevice, MediaPlayerDevice):
|
|||
def __init__(self, device, logical) -> None:
|
||||
"""Initialize the HDMI device."""
|
||||
CecDevice.__init__(self, device, logical)
|
||||
self.entity_id = "{}.{}_{}".format(
|
||||
DOMAIN, "hdmi", hex(self._logical_address)[2:]
|
||||
)
|
||||
self.entity_id = f"{DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
|
||||
def send_keypress(self, key):
|
||||
"""Send keypress to CEC adapter."""
|
||||
|
|
|
@ -28,9 +28,7 @@ class CecSwitchDevice(CecDevice, SwitchDevice):
|
|||
def __init__(self, device, logical) -> None:
|
||||
"""Initialize the HDMI device."""
|
||||
CecDevice.__init__(self, device, logical)
|
||||
self.entity_id = "{}.{}_{}".format(
|
||||
DOMAIN, "hdmi", hex(self._logical_address)[2:]
|
||||
)
|
||||
self.entity_id = f"{DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
|
||||
def turn_on(self, **kwargs) -> None:
|
||||
"""Turn device on."""
|
||||
|
|
|
@ -71,7 +71,7 @@ class N26Account(Entity):
|
|||
@property
|
||||
def name(self) -> str:
|
||||
"""Friendly name of the sensor."""
|
||||
return "n26_{}".format(self._iban[-4:])
|
||||
return f"n26_{self._iban[-4:]}"
|
||||
|
||||
@property
|
||||
def state(self) -> float:
|
||||
|
@ -110,7 +110,7 @@ class N26Account(Entity):
|
|||
}
|
||||
|
||||
for limit in self._data.limits:
|
||||
limit_attr_name = "limit_{}".format(limit["limit"].lower())
|
||||
limit_attr_name = f"limit_{limit['limit'].lower()}"
|
||||
attributes[limit_attr_name] = limit["amount"]
|
||||
|
||||
return attributes
|
||||
|
@ -143,7 +143,7 @@ class N26Card(Entity):
|
|||
@property
|
||||
def name(self) -> str:
|
||||
"""Friendly name of the sensor."""
|
||||
return "{}_card_{}".format(self._account_name.lower(), self._card["id"])
|
||||
return f"{self._account_name.lower()}_card_{self._card['id']}"
|
||||
|
||||
@property
|
||||
def state(self) -> float:
|
||||
|
@ -206,9 +206,7 @@ class N26Space(Entity):
|
|||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique ID of the entity."""
|
||||
return "space_{}_{}".format(
|
||||
self._data.balance["iban"][-4:], self._space["name"].lower()
|
||||
)
|
||||
return f"space_{self._data.balance['iban'][-4:]}_{self._space['name'].lower()}"
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
|
|
@ -42,7 +42,7 @@ class N26CardSwitch(SwitchDevice):
|
|||
@property
|
||||
def name(self) -> str:
|
||||
"""Friendly name of the sensor."""
|
||||
return "card_{}".format(self._card["id"])
|
||||
return f"card_{self._card['id']}"
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
|
|
|
@ -200,7 +200,7 @@ async def async_setup_entry(hass, entry):
|
|||
|
||||
now = datetime.utcnow()
|
||||
trip_id = service.data.get(
|
||||
ATTR_TRIP_ID, "trip_{}".format(int(now.timestamp()))
|
||||
ATTR_TRIP_ID, f"trip_{int(now.timestamp())}"
|
||||
)
|
||||
eta_begin = now + service.data[ATTR_ETA]
|
||||
eta_window = service.data.get(ATTR_ETA_WINDOW, timedelta(minutes=1))
|
||||
|
@ -368,15 +368,11 @@ class NestSensorDevice(Entity):
|
|||
if device is not None:
|
||||
# device specific
|
||||
self.device = device
|
||||
self._name = "{} {}".format(
|
||||
self.device.name_long, self.variable.replace("_", " ")
|
||||
)
|
||||
self._name = f"{self.device.name_long} {self.variable.replace('_', ' ')}"
|
||||
else:
|
||||
# structure only
|
||||
self.device = structure
|
||||
self._name = "{} {}".format(
|
||||
self.structure.name, self.variable.replace("_", " ")
|
||||
)
|
||||
self._name = f"{self.structure.name} {self.variable.replace('_', ' ')}"
|
||||
|
||||
self._state = None
|
||||
self._unit = None
|
||||
|
|
|
@ -57,8 +57,8 @@ class AuthPhase:
|
|||
try:
|
||||
msg = AUTH_MESSAGE_SCHEMA(msg)
|
||||
except vol.Invalid as err:
|
||||
error_msg = "Auth message incorrectly formatted: {}".format(
|
||||
humanize_error(msg, err)
|
||||
error_msg = (
|
||||
f"Auth message incorrectly formatted: {humanize_error(msg, err)}"
|
||||
)
|
||||
self._logger.warning(error_msg)
|
||||
self._send_message(auth_invalid_message(error_msg))
|
||||
|
|
|
@ -233,15 +233,13 @@ def _request_app_setup(hass, config):
|
|||
|
||||
start_url = f"{hass.config.api.base_url}{WINK_AUTH_CALLBACK_PATH}"
|
||||
|
||||
description = """Please create a Wink developer app at
|
||||
description = f"""Please create a Wink developer app at
|
||||
https://developer.wink.com.
|
||||
Add a Redirect URI of {}.
|
||||
Add a Redirect URI of {start_url}.
|
||||
They will provide you a Client ID and secret
|
||||
after reviewing your request.
|
||||
(This can take several days).
|
||||
""".format(
|
||||
start_url
|
||||
)
|
||||
"""
|
||||
|
||||
hass.data[DOMAIN]["configuring"][DOMAIN] = configurator.request_config(
|
||||
DOMAIN,
|
||||
|
@ -351,9 +349,7 @@ def setup(hass, config):
|
|||
# Home .
|
||||
else:
|
||||
|
||||
redirect_uri = "{}{}".format(
|
||||
hass.config.api.base_url, WINK_AUTH_CALLBACK_PATH
|
||||
)
|
||||
redirect_uri = f"{hass.config.api.base_url}{WINK_AUTH_CALLBACK_PATH}"
|
||||
|
||||
wink_auth_start_url = pywink.get_authorization_url(
|
||||
config_file.get(ATTR_CLIENT_ID), redirect_uri
|
||||
|
|
|
@ -58,8 +58,8 @@ class WirelessTagSensor(WirelessTagBaseSensor):
|
|||
# sensor.wirelesstag_bedroom_temperature
|
||||
# and not as sensor.bedroom for temperature and
|
||||
# sensor.bedroom_2 for humidity
|
||||
self._entity_id = "{}.{}_{}_{}".format(
|
||||
"sensor", WIRELESSTAG_DOMAIN, self.underscored_name, self._sensor_type
|
||||
self._entity_id = (
|
||||
f"sensor.{WIRELESSTAG_DOMAIN}_{self.underscored_name}_{self._sensor_type}"
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
|
|
|
@ -57,7 +57,7 @@ class WirelessTagSwitch(WirelessTagBaseSensor, SwitchDevice):
|
|||
super().__init__(api, tag)
|
||||
self._switch_type = switch_type
|
||||
self.sensor_type = SWITCH_TYPES[self._switch_type][1]
|
||||
self._name = "{} {}".format(self._tag.name, SWITCH_TYPES[self._switch_type][0])
|
||||
self._name = f"{self._tag.name} {SWITCH_TYPES[self._switch_type][0]}"
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn on the switch."""
|
||||
|
|
|
@ -320,8 +320,9 @@ class WithingsHealthSensor(Entity):
|
|||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique, Home Assistant friendly identifier for this entity."""
|
||||
return "withings_{}_{}_{}".format(
|
||||
self._slug, self._user_id, slugify(self._attribute.measurement)
|
||||
return (
|
||||
f"withings_{self._slug}_{self._user_id}_"
|
||||
f"{slugify(self._attribute.measurement)}"
|
||||
)
|
||||
|
||||
@property
|
||||
|
|
|
@ -217,9 +217,9 @@ class WUHourlyForecastSensorConfig(WUSensorConfig):
|
|||
:param field: field name to use as value
|
||||
"""
|
||||
super().__init__(
|
||||
friendly_name=lambda wu: "{} {}".format(
|
||||
wu.data["hourly_forecast"][period]["FCTTIME"]["weekday_name_abbrev"],
|
||||
wu.data["hourly_forecast"][period]["FCTTIME"]["civil"],
|
||||
friendly_name=lambda wu: (
|
||||
f"{wu.data['hourly_forecast'][period]['FCTTIME']['weekday_name_abbrev']} "
|
||||
f"{wu.data['hourly_forecast'][period]['FCTTIME']['civil']}"
|
||||
),
|
||||
feature="hourly",
|
||||
value=lambda wu: wu.data["hourly_forecast"][period][field],
|
||||
|
@ -477,8 +477,9 @@ SENSOR_TYPES = {
|
|||
"Wind Summary", "wind_string", "mdi:weather-windy"
|
||||
),
|
||||
"temp_high_record_c": WUAlmanacSensorConfig(
|
||||
lambda wu: "High Temperature Record ({})".format(
|
||||
wu.data["almanac"]["temp_high"]["recordyear"]
|
||||
lambda wu: (
|
||||
f"High Temperature Record "
|
||||
f"({wu.data['almanac']['temp_high']['recordyear']})"
|
||||
),
|
||||
"temp_high",
|
||||
"record",
|
||||
|
@ -487,8 +488,9 @@ SENSOR_TYPES = {
|
|||
"mdi:thermometer",
|
||||
),
|
||||
"temp_high_record_f": WUAlmanacSensorConfig(
|
||||
lambda wu: "High Temperature Record ({})".format(
|
||||
wu.data["almanac"]["temp_high"]["recordyear"]
|
||||
lambda wu: (
|
||||
f"High Temperature Record "
|
||||
f"({wu.data['almanac']['temp_high']['recordyear']})"
|
||||
),
|
||||
"temp_high",
|
||||
"record",
|
||||
|
@ -497,8 +499,9 @@ SENSOR_TYPES = {
|
|||
"mdi:thermometer",
|
||||
),
|
||||
"temp_low_record_c": WUAlmanacSensorConfig(
|
||||
lambda wu: "Low Temperature Record ({})".format(
|
||||
wu.data["almanac"]["temp_low"]["recordyear"]
|
||||
lambda wu: (
|
||||
f"Low Temperature Record "
|
||||
f"({wu.data['almanac']['temp_low']['recordyear']})"
|
||||
),
|
||||
"temp_low",
|
||||
"record",
|
||||
|
@ -507,8 +510,9 @@ SENSOR_TYPES = {
|
|||
"mdi:thermometer",
|
||||
),
|
||||
"temp_low_record_f": WUAlmanacSensorConfig(
|
||||
lambda wu: "Low Temperature Record ({})".format(
|
||||
wu.data["almanac"]["temp_low"]["recordyear"]
|
||||
lambda wu: (
|
||||
f"Low Temperature Record "
|
||||
f"({wu.data['almanac']['temp_low']['recordyear']})"
|
||||
),
|
||||
"temp_low",
|
||||
"record",
|
||||
|
|
|
@ -136,9 +136,7 @@ class XiaomiCamera(Camera):
|
|||
else:
|
||||
video = videos[-1]
|
||||
|
||||
return "ftp://{}:{}@{}:{}{}/{}".format(
|
||||
self.user, self.passwd, host, self.port, ftp.pwd(), video
|
||||
)
|
||||
return f"ftp://{self.user}:{self.passwd}@{host}:{self.port}{ftp.pwd()}/{video}"
|
||||
|
||||
async def async_camera_image(self):
|
||||
"""Return a still image response from the camera."""
|
||||
|
|
|
@ -242,8 +242,8 @@ class XiaomiDevice(Entity):
|
|||
self.parse_voltage(device["data"])
|
||||
|
||||
if hasattr(self, "_data_key") and self._data_key: # pylint: disable=no-member
|
||||
self._unique_id = "{}{}".format(
|
||||
self._data_key, self._sid # pylint: disable=no-member
|
||||
self._unique_id = (
|
||||
f"{self._data_key}{self._sid}" # pylint: disable=no-member
|
||||
)
|
||||
else:
|
||||
self._unique_id = f"{self._type}{self._sid}"
|
||||
|
|
|
@ -718,7 +718,7 @@ class XiaomiPhilipsEyecareLampAmbientLight(XiaomiPhilipsAbstractLight):
|
|||
"""Initialize the light device."""
|
||||
name = f"{name} Ambient Light"
|
||||
if unique_id is not None:
|
||||
unique_id = "{}-{}".format(unique_id, "ambient")
|
||||
unique_id = f"{unique_id}-ambient"
|
||||
super().__init__(name, light, model, unique_id)
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
|
|
|
@ -429,7 +429,7 @@ class ChuangMiPlugSwitch(XiaomiPlugGenericSwitch):
|
|||
name = f"{name} USB" if channel_usb else name
|
||||
|
||||
if unique_id is not None and channel_usb:
|
||||
unique_id = "{}-{}".format(unique_id, "usb")
|
||||
unique_id = f"{unique_id}-usb"
|
||||
|
||||
super().__init__(name, plug, model, unique_id)
|
||||
self._channel_usb = channel_usb
|
||||
|
|
|
@ -110,14 +110,9 @@ class YiCamera(Camera):
|
|||
|
||||
await ftp.quit()
|
||||
self._is_on = True
|
||||
return "ftp://{}:{}@{}:{}{}/{}/{}".format(
|
||||
self.user,
|
||||
self.passwd,
|
||||
self.host,
|
||||
self.port,
|
||||
self.path,
|
||||
latest_dir,
|
||||
videos[-1],
|
||||
return (
|
||||
f"ftp://{self.user}:{self.passwd}@{self.host}:"
|
||||
f"{self.port}{self.path}/{latest_dir}/{videos[-1]}"
|
||||
)
|
||||
except (ConnectionRefusedError, StatusCodeError) as err:
|
||||
_LOGGER.error("Error while fetching video: %s", err)
|
||||
|
|
|
@ -159,7 +159,7 @@ class ZamgData:
|
|||
"""The class for handling the data retrieval."""
|
||||
|
||||
API_URL = "http://www.zamg.ac.at/ogd/"
|
||||
API_HEADERS = {USER_AGENT: "{} {}".format("home-assistant.zamg/", __version__)}
|
||||
API_HEADERS = {USER_AGENT: f"home-assistant.zamg/ {__version__}"}
|
||||
|
||||
def __init__(self, station_id):
|
||||
"""Initialize the probe."""
|
||||
|
|
|
@ -78,8 +78,9 @@ class ZamgWeather(WeatherEntity):
|
|||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self.stationname or "ZAMG {}".format(
|
||||
self.zamg_data.data.get("Name") or "(unknown station)"
|
||||
return (
|
||||
self.stationname
|
||||
or f"ZAMG {self.zamg_data.data.get('Name') or '(unknown station)'}"
|
||||
)
|
||||
|
||||
@property
|
||||
|
|
|
@ -93,9 +93,7 @@ class ZHADevice(LogMixin):
|
|||
self._zigpy_device = zigpy_device
|
||||
self._zha_gateway = zha_gateway
|
||||
self._available = False
|
||||
self._available_signal = "{}_{}_{}".format(
|
||||
self.name, self.ieee, SIGNAL_AVAILABLE
|
||||
)
|
||||
self._available_signal = f"{self.name}_{self.ieee}_{SIGNAL_AVAILABLE}"
|
||||
self._checkins_missed_count = 0
|
||||
self.unsubs = []
|
||||
self.unsubs.append(
|
||||
|
@ -104,10 +102,11 @@ class ZHADevice(LogMixin):
|
|||
)
|
||||
)
|
||||
self.quirk_applied = isinstance(self._zigpy_device, zigpy.quirks.CustomDevice)
|
||||
self.quirk_class = "{}.{}".format(
|
||||
self._zigpy_device.__class__.__module__,
|
||||
self._zigpy_device.__class__.__name__,
|
||||
self.quirk_class = (
|
||||
f"{self._zigpy_device.__class__.__module__}."
|
||||
f"{self._zigpy_device.__class__.__name__}"
|
||||
)
|
||||
|
||||
if self.is_mains_powered:
|
||||
self._consider_unavailable_time = _CONSIDER_UNAVAILABLE_MAINS
|
||||
else:
|
||||
|
@ -352,9 +351,7 @@ class ZHADevice(LogMixin):
|
|||
if self._available != available and available:
|
||||
# Update the state the first time the device comes online
|
||||
async_dispatcher_send(self.hass, self._available_signal, False)
|
||||
async_dispatcher_send(
|
||||
self.hass, "{}_{}".format(self._available_signal, "entity"), available
|
||||
)
|
||||
async_dispatcher_send(self.hass, f"{self._available_signal}_entity", available)
|
||||
self._available = available
|
||||
|
||||
@property
|
||||
|
|
|
@ -119,7 +119,7 @@ class BaseZhaEntity(RestoreEntity, LogMixin, entity.Entity):
|
|||
self.remove_future = asyncio.Future()
|
||||
await self.async_accept_signal(
|
||||
None,
|
||||
"{}_{}".format(SIGNAL_REMOVE, str(self.zha_device.ieee)),
|
||||
f"{SIGNAL_REMOVE}_{self.zha_device.ieee}",
|
||||
self.async_remove,
|
||||
signal_override=True,
|
||||
)
|
||||
|
@ -182,7 +182,7 @@ class ZhaEntity(BaseZhaEntity):
|
|||
await self.async_check_recently_seen()
|
||||
await self.async_accept_signal(
|
||||
None,
|
||||
"{}_{}".format(self.zha_device.available_signal, "entity"),
|
||||
f"{self.zha_device.available_signal}_entity",
|
||||
self.async_set_available,
|
||||
signal_override=True,
|
||||
)
|
||||
|
|
|
@ -261,7 +261,7 @@ def _obj_to_dict(obj):
|
|||
|
||||
def _value_name(value):
|
||||
"""Return the name of the value."""
|
||||
return "{} {}".format(node_name(value.node), value.label).strip()
|
||||
return f"{node_name(value.node)} {value.label}".strip()
|
||||
|
||||
|
||||
def nice_print_node(node):
|
||||
|
@ -826,9 +826,7 @@ async def async_setup_entry(hass, config_entry):
|
|||
)
|
||||
return
|
||||
_LOGGER.info(
|
||||
"Node %s on instance %s does not have resettable meters.",
|
||||
node_id,
|
||||
instance,
|
||||
"Node %s on instance %s does not have resettable meters.", node_id, instance
|
||||
)
|
||||
|
||||
def heal_node(service):
|
||||
|
|
|
@ -337,21 +337,20 @@ class ZwaveLock(ZWaveDeviceEntity, LockDevice):
|
|||
)
|
||||
|
||||
if alarm_type == 21:
|
||||
self._lock_status = "{}{}".format(
|
||||
LOCK_ALARM_TYPE.get(str(alarm_type)),
|
||||
MANUAL_LOCK_ALARM_LEVEL.get(str(alarm_level)),
|
||||
self._lock_status = (
|
||||
f"{LOCK_ALARM_TYPE.get(str(alarm_type))}"
|
||||
f"{MANUAL_LOCK_ALARM_LEVEL.get(str(alarm_level))}"
|
||||
)
|
||||
return
|
||||
if str(alarm_type) in ALARM_TYPE_STD:
|
||||
self._lock_status = "{}{}".format(
|
||||
LOCK_ALARM_TYPE.get(str(alarm_type)), str(alarm_level)
|
||||
)
|
||||
self._lock_status = f"{LOCK_ALARM_TYPE.get(str(alarm_type))}{alarm_level}"
|
||||
return
|
||||
if alarm_type == 161:
|
||||
self._lock_status = "{}{}".format(
|
||||
LOCK_ALARM_TYPE.get(str(alarm_type)),
|
||||
TAMPER_ALARM_LEVEL.get(str(alarm_level)),
|
||||
self._lock_status = (
|
||||
f"{LOCK_ALARM_TYPE.get(str(alarm_type))}"
|
||||
f"{TAMPER_ALARM_LEVEL.get(str(alarm_level))}"
|
||||
)
|
||||
|
||||
return
|
||||
if alarm_type != 0:
|
||||
self._lock_status = LOCK_ALARM_TYPE.get(str(alarm_type))
|
||||
|
|
|
@ -116,10 +116,9 @@ def _no_duplicate_auth_provider(
|
|||
key = (config[CONF_TYPE], config.get(CONF_ID))
|
||||
if key in config_keys:
|
||||
raise vol.Invalid(
|
||||
"Duplicate auth provider {} found. Please add unique IDs if "
|
||||
"you want to have the same auth provider twice".format(
|
||||
config[CONF_TYPE]
|
||||
)
|
||||
f"Duplicate auth provider {config[CONF_TYPE]} found. "
|
||||
"Please add unique IDs "
|
||||
"if you want to have the same auth provider twice"
|
||||
)
|
||||
config_keys.add(key)
|
||||
return configs
|
||||
|
@ -140,8 +139,9 @@ def _no_duplicate_auth_mfa_module(
|
|||
key = config.get(CONF_ID, config[CONF_TYPE])
|
||||
if key in config_keys:
|
||||
raise vol.Invalid(
|
||||
"Duplicate mfa module {} found. Please add unique IDs if "
|
||||
"you want to have the same mfa module twice".format(config[CONF_TYPE])
|
||||
f"Duplicate mfa module {config[CONF_TYPE]} found. "
|
||||
"Please add unique IDs "
|
||||
"if you want to have the same mfa module twice"
|
||||
)
|
||||
config_keys.add(key)
|
||||
return configs
|
||||
|
@ -319,8 +319,9 @@ def load_yaml_config_file(config_path: str) -> Dict[Any, Any]:
|
|||
conf_dict = load_yaml(config_path)
|
||||
|
||||
if not isinstance(conf_dict, dict):
|
||||
msg = "The configuration file {} does not contain a dictionary".format(
|
||||
os.path.basename(config_path)
|
||||
msg = (
|
||||
f"The configuration file {os.path.basename(config_path)} "
|
||||
"does not contain a dictionary"
|
||||
)
|
||||
_LOGGER.error(msg)
|
||||
raise HomeAssistantError(msg)
|
||||
|
@ -415,16 +416,13 @@ def _format_config_error(
|
|||
message = f"Invalid config for [{domain}]: "
|
||||
if isinstance(ex, vol.Invalid):
|
||||
if "extra keys not allowed" in ex.error_message:
|
||||
path = "->".join(str(m) for m in ex.path)
|
||||
message += (
|
||||
"[{option}] is an invalid option for [{domain}]. "
|
||||
"Check: {domain}->{path}.".format(
|
||||
option=ex.path[-1],
|
||||
domain=domain,
|
||||
path="->".join(str(m) for m in ex.path),
|
||||
)
|
||||
f"[{ex.path[-1]}] is an invalid option for [{domain}]. "
|
||||
f"Check: {domain}->{path}."
|
||||
)
|
||||
else:
|
||||
message += "{}.".format(humanize_error(config, ex))
|
||||
message += f"{humanize_error(config, ex)}."
|
||||
else:
|
||||
message += str(ex)
|
||||
|
||||
|
@ -433,9 +431,9 @@ def _format_config_error(
|
|||
except AttributeError:
|
||||
domain_config = config
|
||||
|
||||
message += " (See {}, line {}). ".format(
|
||||
getattr(domain_config, "__config_file__", "?"),
|
||||
getattr(domain_config, "__line__", "?"),
|
||||
message += (
|
||||
f" (See {getattr(domain_config, '__config_file__', '?')}, "
|
||||
f"line {getattr(domain_config, '__line__', '?')}). "
|
||||
)
|
||||
|
||||
if domain != CONF_CORE and link:
|
||||
|
@ -551,9 +549,9 @@ def _log_pkg_error(package: str, component: str, config: Dict, message: str) ->
|
|||
message = f"Package {package} setup failed. Integration {component} {message}"
|
||||
|
||||
pack_config = config[CONF_CORE][CONF_PACKAGES].get(package, config)
|
||||
message += " (See {}:{}). ".format(
|
||||
getattr(pack_config, "__config_file__", "?"),
|
||||
getattr(pack_config, "__line__", "?"),
|
||||
message += (
|
||||
f" (See {getattr(pack_config, '__config_file__', '?')}:"
|
||||
f"{getattr(pack_config, '__line__', '?')}). "
|
||||
)
|
||||
|
||||
_LOGGER.error(message)
|
||||
|
|
|
@ -179,9 +179,7 @@ class FlowManager(abc.ABC):
|
|||
RESULT_TYPE_ABORT,
|
||||
RESULT_TYPE_EXTERNAL_STEP_DONE,
|
||||
):
|
||||
raise ValueError(
|
||||
"Handler returned incorrect type: {}".format(result["type"])
|
||||
)
|
||||
raise ValueError(f"Handler returned incorrect type: {result['type']}")
|
||||
|
||||
if result["type"] in (
|
||||
RESULT_TYPE_FORM,
|
||||
|
|
|
@ -146,7 +146,7 @@ class EntityRegistry:
|
|||
Conflicts checked against registered and currently existing entities.
|
||||
"""
|
||||
return ensure_unique_string(
|
||||
"{}.{}".format(domain, slugify(suggested_object_id)),
|
||||
f"{domain}.{slugify(suggested_object_id)}",
|
||||
chain(
|
||||
self.entities.keys(),
|
||||
self.hass.states.async_entity_ids(domain),
|
||||
|
|
|
@ -425,8 +425,7 @@ def _load_file(
|
|||
|
||||
if str(err) not in white_listed_errors:
|
||||
_LOGGER.exception(
|
||||
("Error loading %s. Make sure all dependencies are installed"),
|
||||
path,
|
||||
("Error loading %s. Make sure all dependencies are installed"), path
|
||||
)
|
||||
|
||||
return None
|
||||
|
|
|
@ -233,9 +233,7 @@ def line_info(obj, **kwargs):
|
|||
"""Display line config source."""
|
||||
if hasattr(obj, "__config_file__"):
|
||||
return color(
|
||||
"cyan",
|
||||
"[source {}:{}]".format(obj.__config_file__, obj.__line__ or "?"),
|
||||
**kwargs,
|
||||
"cyan", f"[source {obj.__config_file__}:{obj.__line__ or '?'}]", **kwargs
|
||||
)
|
||||
return "?"
|
||||
|
||||
|
|
|
@ -54,9 +54,8 @@ def _yaml_unsupported(
|
|||
constructor: ExtSafeConstructor, node: ruamel.yaml.nodes.Node
|
||||
) -> None:
|
||||
raise UnsupportedYamlError(
|
||||
"Unsupported YAML, you can not use {} in {}".format(
|
||||
node.tag, os.path.basename(constructor.name or "(None)")
|
||||
)
|
||||
f"Unsupported YAML, you can not use {node.tag} in "
|
||||
f"{os.path.basename(constructor.name or '(None)')}"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ def gather_requirements_from_modules(errors, reqs):
|
|||
try:
|
||||
module = importlib.import_module(package)
|
||||
except ImportError as err:
|
||||
print("{}.py: {}".format(package.replace(".", "/"), err))
|
||||
print(f"{package.replace('.', '/')}.py: {err}")
|
||||
errors.append(package)
|
||||
continue
|
||||
|
||||
|
|
|
@ -48,9 +48,7 @@ def generate_and_validate(integrations: Dict[str, Integration]):
|
|||
"codeowners", "Code owners need to be valid GitHub handles."
|
||||
)
|
||||
|
||||
parts.append(
|
||||
"homeassistant/components/{}/* {}".format(domain, " ".join(codeowners))
|
||||
)
|
||||
parts.append(f"homeassistant/components/{domain}/* {' '.join(codeowners)}")
|
||||
|
||||
parts.append(f"\n{INDIVIDUAL_FILES.strip()}")
|
||||
|
||||
|
|
|
@ -12,12 +12,7 @@ DOCUMENTATION_URL_HOST = "www.home-assistant.io"
|
|||
DOCUMENTATION_URL_PATH_PREFIX = "/integrations/"
|
||||
DOCUMENTATION_URL_EXCEPTIONS = ["https://www.home-assistant.io/hassio"]
|
||||
|
||||
SUPPORTED_QUALITY_SCALES = [
|
||||
"gold",
|
||||
"internal",
|
||||
"platinum",
|
||||
"silver",
|
||||
]
|
||||
SUPPORTED_QUALITY_SCALES = ["gold", "internal", "platinum", "silver"]
|
||||
|
||||
|
||||
def documentation_url(value: str) -> str:
|
||||
|
@ -68,8 +63,7 @@ def validate_manifest(integration: Integration):
|
|||
MANIFEST_SCHEMA(integration.manifest)
|
||||
except vol.Invalid as err:
|
||||
integration.add_error(
|
||||
"manifest",
|
||||
"Invalid manifest: {}".format(humanize_error(integration.manifest, err)),
|
||||
"manifest", f"Invalid manifest: {humanize_error(integration.manifest, err)}"
|
||||
)
|
||||
integration.manifest = None
|
||||
return
|
||||
|
|
|
@ -79,7 +79,7 @@ def validate_services(integration: Integration):
|
|||
SERVICES_SCHEMA(data)
|
||||
except vol.Invalid as err:
|
||||
integration.add_error(
|
||||
"services", "Invalid services.yaml: {}".format(humanize_error(data, err))
|
||||
"services", f"Invalid services.yaml: {humanize_error(data, err)}"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -79,8 +79,8 @@ def generate_and_validate(integrations: Dict[str, Integration]):
|
|||
if model in homekit_dict:
|
||||
integration.add_error(
|
||||
"zeroconf",
|
||||
"Integrations {} and {} have overlapping HomeKit "
|
||||
"models".format(domain, homekit_dict[model]),
|
||||
f"Integrations {domain} and {homekit_dict[model]} "
|
||||
"have overlapping HomeKit models",
|
||||
)
|
||||
break
|
||||
|
||||
|
@ -100,8 +100,8 @@ def generate_and_validate(integrations: Dict[str, Integration]):
|
|||
if key.startswith(key_2) or key_2.startswith(key):
|
||||
integration.add_error(
|
||||
"zeroconf",
|
||||
"Integrations {} and {} have overlapping HomeKit "
|
||||
"models".format(homekit_dict[key], homekit_dict[key_2]),
|
||||
f"Integrations {homekit_dict[key]} and {homekit_dict[key_2]} "
|
||||
"have overlapping HomeKit models",
|
||||
)
|
||||
warned.add(key)
|
||||
warned.add(key_2)
|
||||
|
|
|
@ -61,7 +61,7 @@ async def async_exec(*args, display=False):
|
|||
argsp = []
|
||||
for arg in args:
|
||||
if os.path.isfile(arg):
|
||||
argsp.append("\\\n {}".format(shlex.quote(arg)))
|
||||
argsp.append(f"\\\n {shlex.quote(arg)}")
|
||||
else:
|
||||
argsp.append(shlex.quote(arg))
|
||||
printc("cyan", *argsp)
|
||||
|
@ -75,9 +75,7 @@ async def async_exec(*args, display=False):
|
|||
kwargs["stderr"] = asyncio.subprocess.PIPE
|
||||
proc = await asyncio.create_subprocess_exec(*args, **kwargs)
|
||||
except FileNotFoundError as err:
|
||||
printc(
|
||||
FAIL, f"Could not execute {args[0]}. Did you install test requirements?",
|
||||
)
|
||||
printc(FAIL, f"Could not execute {args[0]}. Did you install test requirements?")
|
||||
raise err
|
||||
|
||||
if not display:
|
||||
|
|
Loading…
Reference in New Issue