mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 21:06:19 +00:00
Black
This commit is contained in:
@@ -20,32 +20,33 @@ from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ERROR_LOG_FILENAME = 'home-assistant.log'
|
||||
ERROR_LOG_FILENAME = "home-assistant.log"
|
||||
|
||||
# hass.data key for logging information.
|
||||
DATA_LOGGING = 'logging'
|
||||
DATA_LOGGING = "logging"
|
||||
|
||||
DEBUGGER_INTEGRATIONS = {'ptvsd', }
|
||||
CORE_INTEGRATIONS = ('homeassistant', 'persistent_notification')
|
||||
LOGGING_INTEGRATIONS = {'logger', 'system_log'}
|
||||
DEBUGGER_INTEGRATIONS = {"ptvsd"}
|
||||
CORE_INTEGRATIONS = ("homeassistant", "persistent_notification")
|
||||
LOGGING_INTEGRATIONS = {"logger", "system_log"}
|
||||
STAGE_1_INTEGRATIONS = {
|
||||
# To record data
|
||||
'recorder',
|
||||
"recorder",
|
||||
# To make sure we forward data to other instances
|
||||
'mqtt_eventstream',
|
||||
"mqtt_eventstream",
|
||||
}
|
||||
|
||||
|
||||
async def async_from_config_dict(config: Dict[str, Any],
|
||||
hass: core.HomeAssistant,
|
||||
config_dir: Optional[str] = None,
|
||||
enable_log: bool = True,
|
||||
verbose: bool = False,
|
||||
skip_pip: bool = False,
|
||||
log_rotate_days: Any = None,
|
||||
log_file: Any = None,
|
||||
log_no_color: bool = False) \
|
||||
-> Optional[core.HomeAssistant]:
|
||||
async def async_from_config_dict(
|
||||
config: Dict[str, Any],
|
||||
hass: core.HomeAssistant,
|
||||
config_dir: Optional[str] = None,
|
||||
enable_log: bool = True,
|
||||
verbose: bool = False,
|
||||
skip_pip: bool = False,
|
||||
log_rotate_days: Any = None,
|
||||
log_file: Any = None,
|
||||
log_no_color: bool = False,
|
||||
) -> Optional[core.HomeAssistant]:
|
||||
"""Try to configure Home Assistant from a configuration dictionary.
|
||||
|
||||
Dynamically loads required components and its dependencies.
|
||||
@@ -54,28 +55,30 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||
start = time()
|
||||
|
||||
if enable_log:
|
||||
async_enable_logging(hass, verbose, log_rotate_days, log_file,
|
||||
log_no_color)
|
||||
async_enable_logging(hass, verbose, log_rotate_days, log_file, log_no_color)
|
||||
|
||||
hass.config.skip_pip = skip_pip
|
||||
if skip_pip:
|
||||
_LOGGER.warning("Skipping pip installation of required modules. "
|
||||
"This may cause issues")
|
||||
_LOGGER.warning(
|
||||
"Skipping pip installation of required modules. " "This may cause issues"
|
||||
)
|
||||
|
||||
core_config = config.get(core.DOMAIN, {})
|
||||
api_password = config.get('http', {}).get('api_password')
|
||||
trusted_networks = config.get('http', {}).get('trusted_networks')
|
||||
api_password = config.get("http", {}).get("api_password")
|
||||
trusted_networks = config.get("http", {}).get("trusted_networks")
|
||||
|
||||
try:
|
||||
await conf_util.async_process_ha_core_config(
|
||||
hass, core_config, api_password, trusted_networks)
|
||||
hass, core_config, api_password, trusted_networks
|
||||
)
|
||||
except vol.Invalid as config_err:
|
||||
conf_util.async_log_exception(
|
||||
config_err, 'homeassistant', core_config, hass)
|
||||
conf_util.async_log_exception(config_err, "homeassistant", core_config, hass)
|
||||
return None
|
||||
except HomeAssistantError:
|
||||
_LOGGER.error("Home Assistant core failed to initialize. "
|
||||
"Further initialization aborted")
|
||||
_LOGGER.error(
|
||||
"Home Assistant core failed to initialize. "
|
||||
"Further initialization aborted"
|
||||
)
|
||||
return None
|
||||
|
||||
# Make a copy because we are mutating it.
|
||||
@@ -83,7 +86,8 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||
|
||||
# Merge packages
|
||||
await conf_util.merge_packages_config(
|
||||
hass, config, core_config.get(conf_util.CONF_PACKAGES, {}))
|
||||
hass, config, core_config.get(conf_util.CONF_PACKAGES, {})
|
||||
)
|
||||
|
||||
hass.config_entries = config_entries.ConfigEntries(hass, config)
|
||||
await hass.config_entries.async_initialize()
|
||||
@@ -91,19 +95,20 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||
await _async_set_up_integrations(hass, config)
|
||||
|
||||
stop = time()
|
||||
_LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
|
||||
_LOGGER.info("Home Assistant initialized in %.2fs", stop - start)
|
||||
|
||||
return hass
|
||||
|
||||
|
||||
async def async_from_config_file(config_path: str,
|
||||
hass: core.HomeAssistant,
|
||||
verbose: bool = False,
|
||||
skip_pip: bool = True,
|
||||
log_rotate_days: Any = None,
|
||||
log_file: Any = None,
|
||||
log_no_color: bool = False)\
|
||||
-> Optional[core.HomeAssistant]:
|
||||
async def async_from_config_file(
|
||||
config_path: str,
|
||||
hass: core.HomeAssistant,
|
||||
verbose: bool = False,
|
||||
skip_pip: bool = True,
|
||||
log_rotate_days: Any = None,
|
||||
log_file: Any = None,
|
||||
log_no_color: bool = False,
|
||||
) -> Optional[core.HomeAssistant]:
|
||||
"""Read the configuration file and try to start all the functionality.
|
||||
|
||||
Will add functionality to 'hass' parameter.
|
||||
@@ -116,15 +121,14 @@ async def async_from_config_file(config_path: str,
|
||||
if not is_virtual_env():
|
||||
await async_mount_local_lib_path(config_dir)
|
||||
|
||||
async_enable_logging(hass, verbose, log_rotate_days, log_file,
|
||||
log_no_color)
|
||||
async_enable_logging(hass, verbose, log_rotate_days, log_file, log_no_color)
|
||||
|
||||
await hass.async_add_executor_job(
|
||||
conf_util.process_ha_config_upgrade, hass)
|
||||
await hass.async_add_executor_job(conf_util.process_ha_config_upgrade, hass)
|
||||
|
||||
try:
|
||||
config_dict = await hass.async_add_executor_job(
|
||||
conf_util.load_yaml_config_file, config_path)
|
||||
conf_util.load_yaml_config_file, config_path
|
||||
)
|
||||
except HomeAssistantError as err:
|
||||
_LOGGER.error("Error loading %s: %s", config_path, err)
|
||||
return None
|
||||
@@ -132,43 +136,48 @@ async def async_from_config_file(config_path: str,
|
||||
clear_secret_cache()
|
||||
|
||||
return await async_from_config_dict(
|
||||
config_dict, hass, enable_log=False, skip_pip=skip_pip)
|
||||
config_dict, hass, enable_log=False, skip_pip=skip_pip
|
||||
)
|
||||
|
||||
|
||||
@core.callback
|
||||
def async_enable_logging(hass: core.HomeAssistant,
|
||||
verbose: bool = False,
|
||||
log_rotate_days: Optional[int] = None,
|
||||
log_file: Optional[str] = None,
|
||||
log_no_color: bool = False) -> None:
|
||||
def async_enable_logging(
|
||||
hass: core.HomeAssistant,
|
||||
verbose: bool = False,
|
||||
log_rotate_days: Optional[int] = None,
|
||||
log_file: Optional[str] = None,
|
||||
log_no_color: bool = False,
|
||||
) -> None:
|
||||
"""Set up the logging.
|
||||
|
||||
This method must be run in the event loop.
|
||||
"""
|
||||
fmt = ("%(asctime)s %(levelname)s (%(threadName)s) "
|
||||
"[%(name)s] %(message)s")
|
||||
datefmt = '%Y-%m-%d %H:%M:%S'
|
||||
fmt = "%(asctime)s %(levelname)s (%(threadName)s) " "[%(name)s] %(message)s"
|
||||
datefmt = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
if not log_no_color:
|
||||
try:
|
||||
from colorlog import ColoredFormatter
|
||||
|
||||
# basicConfig must be called after importing colorlog in order to
|
||||
# ensure that the handlers it sets up wraps the correct streams.
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
|
||||
logging.getLogger().handlers[0].setFormatter(ColoredFormatter(
|
||||
colorfmt,
|
||||
datefmt=datefmt,
|
||||
reset=True,
|
||||
log_colors={
|
||||
'DEBUG': 'cyan',
|
||||
'INFO': 'green',
|
||||
'WARNING': 'yellow',
|
||||
'ERROR': 'red',
|
||||
'CRITICAL': 'red',
|
||||
}
|
||||
))
|
||||
logging.getLogger().handlers[0].setFormatter(
|
||||
ColoredFormatter(
|
||||
colorfmt,
|
||||
datefmt=datefmt,
|
||||
reset=True,
|
||||
log_colors={
|
||||
"DEBUG": "cyan",
|
||||
"INFO": "green",
|
||||
"WARNING": "yellow",
|
||||
"ERROR": "red",
|
||||
"CRITICAL": "red",
|
||||
},
|
||||
)
|
||||
)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -177,9 +186,9 @@ def async_enable_logging(hass: core.HomeAssistant,
|
||||
logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO)
|
||||
|
||||
# Suppress overly verbose logs from libraries that aren't helpful
|
||||
logging.getLogger('requests').setLevel(logging.WARNING)
|
||||
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
||||
logging.getLogger('aiohttp.access').setLevel(logging.WARNING)
|
||||
logging.getLogger("requests").setLevel(logging.WARNING)
|
||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||
logging.getLogger("aiohttp.access").setLevel(logging.WARNING)
|
||||
|
||||
# Log errors to a file if we have write access to file or config dir
|
||||
if log_file is None:
|
||||
@@ -192,16 +201,16 @@ def async_enable_logging(hass: core.HomeAssistant,
|
||||
|
||||
# Check if we can write to the error log if it exists or that
|
||||
# we can create files in the containing directory if not.
|
||||
if (err_path_exists and os.access(err_log_path, os.W_OK)) or \
|
||||
(not err_path_exists and os.access(err_dir, os.W_OK)):
|
||||
if (err_path_exists and os.access(err_log_path, os.W_OK)) or (
|
||||
not err_path_exists and os.access(err_dir, os.W_OK)
|
||||
):
|
||||
|
||||
if log_rotate_days:
|
||||
err_handler = logging.handlers.TimedRotatingFileHandler(
|
||||
err_log_path, when='midnight',
|
||||
backupCount=log_rotate_days) # type: logging.FileHandler
|
||||
err_log_path, when="midnight", backupCount=log_rotate_days
|
||||
) # type: logging.FileHandler
|
||||
else:
|
||||
err_handler = logging.FileHandler(
|
||||
err_log_path, mode='w', delay=True)
|
||||
err_handler = logging.FileHandler(err_log_path, mode="w", delay=True)
|
||||
|
||||
err_handler.setLevel(logging.INFO if verbose else logging.WARNING)
|
||||
err_handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt))
|
||||
@@ -210,21 +219,19 @@ def async_enable_logging(hass: core.HomeAssistant,
|
||||
|
||||
async def async_stop_async_handler(_: Any) -> None:
|
||||
"""Cleanup async handler."""
|
||||
logging.getLogger('').removeHandler(async_handler) # type: ignore
|
||||
logging.getLogger("").removeHandler(async_handler) # type: ignore
|
||||
await async_handler.async_close(blocking=True)
|
||||
|
||||
hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_CLOSE, async_stop_async_handler)
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, async_stop_async_handler)
|
||||
|
||||
logger = logging.getLogger('')
|
||||
logger = logging.getLogger("")
|
||||
logger.addHandler(async_handler) # type: ignore
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Save the log file location for access by other components.
|
||||
hass.data[DATA_LOGGING] = err_log_path
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Unable to set up error log %s (access denied)", err_log_path)
|
||||
_LOGGER.error("Unable to set up error log %s (access denied)", err_log_path)
|
||||
|
||||
|
||||
async def async_mount_local_lib_path(config_dir: str) -> str:
|
||||
@@ -232,7 +239,7 @@ async def async_mount_local_lib_path(config_dir: str) -> str:
|
||||
|
||||
This function is a coroutine.
|
||||
"""
|
||||
deps_dir = os.path.join(config_dir, 'deps')
|
||||
deps_dir = os.path.join(config_dir, "deps")
|
||||
lib_dir = await async_get_user_site(deps_dir)
|
||||
if lib_dir not in sys.path:
|
||||
sys.path.insert(0, lib_dir)
|
||||
@@ -243,21 +250,21 @@ async def async_mount_local_lib_path(config_dir: str) -> str:
|
||||
def _get_domains(hass: core.HomeAssistant, config: Dict[str, Any]) -> Set[str]:
|
||||
"""Get domains of components to set up."""
|
||||
# Filter out the repeating and common config section [homeassistant]
|
||||
domains = set(key.split(' ')[0] for key in config.keys()
|
||||
if key != core.DOMAIN)
|
||||
domains = set(key.split(" ")[0] for key in config.keys() if key != core.DOMAIN)
|
||||
|
||||
# Add config entry domains
|
||||
domains.update(hass.config_entries.async_domains()) # type: ignore
|
||||
|
||||
# Make sure the Hass.io component is loaded
|
||||
if 'HASSIO' in os.environ:
|
||||
domains.add('hassio')
|
||||
if "HASSIO" in os.environ:
|
||||
domains.add("hassio")
|
||||
|
||||
return domains
|
||||
|
||||
|
||||
async def _async_set_up_integrations(
|
||||
hass: core.HomeAssistant, config: Dict[str, Any]) -> None:
|
||||
hass: core.HomeAssistant, config: Dict[str, Any]
|
||||
) -> None:
|
||||
"""Set up all the integrations."""
|
||||
domains = _get_domains(hass, config)
|
||||
|
||||
@@ -265,27 +272,33 @@ async def _async_set_up_integrations(
|
||||
debuggers = domains & DEBUGGER_INTEGRATIONS
|
||||
if debuggers:
|
||||
_LOGGER.debug("Starting up debuggers %s", debuggers)
|
||||
await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in debuggers))
|
||||
await asyncio.gather(
|
||||
*(async_setup_component(hass, domain, config) for domain in debuggers)
|
||||
)
|
||||
domains -= DEBUGGER_INTEGRATIONS
|
||||
|
||||
# Resolve all dependencies of all components so we can find the logging
|
||||
# and integrations that need faster initialization.
|
||||
resolved_domains_task = asyncio.gather(*(
|
||||
loader.async_component_dependencies(hass, domain)
|
||||
for domain in domains
|
||||
), return_exceptions=True)
|
||||
resolved_domains_task = asyncio.gather(
|
||||
*(loader.async_component_dependencies(hass, domain) for domain in domains),
|
||||
return_exceptions=True,
|
||||
)
|
||||
|
||||
# Set up core.
|
||||
_LOGGER.debug("Setting up %s", CORE_INTEGRATIONS)
|
||||
|
||||
if not all(await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in CORE_INTEGRATIONS
|
||||
))):
|
||||
_LOGGER.error("Home Assistant core failed to initialize. "
|
||||
"Further initialization aborted")
|
||||
if not all(
|
||||
await asyncio.gather(
|
||||
*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in CORE_INTEGRATIONS
|
||||
)
|
||||
)
|
||||
):
|
||||
_LOGGER.error(
|
||||
"Home Assistant core failed to initialize. "
|
||||
"Further initialization aborted"
|
||||
)
|
||||
return
|
||||
|
||||
_LOGGER.debug("Home Assistant core initialized")
|
||||
@@ -305,36 +318,32 @@ async def _async_set_up_integrations(
|
||||
if logging_domains:
|
||||
_LOGGER.info("Setting up %s", logging_domains)
|
||||
|
||||
await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in logging_domains
|
||||
))
|
||||
await asyncio.gather(
|
||||
*(async_setup_component(hass, domain, config) for domain in logging_domains)
|
||||
)
|
||||
|
||||
# Kick off loading the registries. They don't need to be awaited.
|
||||
asyncio.gather(
|
||||
hass.helpers.device_registry.async_get_registry(),
|
||||
hass.helpers.entity_registry.async_get_registry(),
|
||||
hass.helpers.area_registry.async_get_registry())
|
||||
hass.helpers.area_registry.async_get_registry(),
|
||||
)
|
||||
|
||||
if stage_1_domains:
|
||||
await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in stage_1_domains
|
||||
))
|
||||
await asyncio.gather(
|
||||
*(async_setup_component(hass, domain, config) for domain in stage_1_domains)
|
||||
)
|
||||
|
||||
# Load all integrations
|
||||
after_dependencies = {} # type: Dict[str, Set[str]]
|
||||
|
||||
for int_or_exc in await asyncio.gather(*(
|
||||
loader.async_get_integration(hass, domain)
|
||||
for domain in stage_2_domains
|
||||
), return_exceptions=True):
|
||||
for int_or_exc in await asyncio.gather(
|
||||
*(loader.async_get_integration(hass, domain) for domain in stage_2_domains),
|
||||
return_exceptions=True,
|
||||
):
|
||||
# Exceptions are handled in async_setup_component.
|
||||
if (isinstance(int_or_exc, loader.Integration) and
|
||||
int_or_exc.after_dependencies):
|
||||
after_dependencies[int_or_exc.domain] = set(
|
||||
int_or_exc.after_dependencies
|
||||
)
|
||||
if isinstance(int_or_exc, loader.Integration) and int_or_exc.after_dependencies:
|
||||
after_dependencies[int_or_exc.domain] = set(int_or_exc.after_dependencies)
|
||||
|
||||
last_load = None
|
||||
while stage_2_domains:
|
||||
@@ -344,8 +353,7 @@ async def _async_set_up_integrations(
|
||||
after_deps = after_dependencies.get(domain)
|
||||
# Load if integration has no after_dependencies or they are
|
||||
# all loaded
|
||||
if (not after_deps or
|
||||
not after_deps-hass.config.components):
|
||||
if not after_deps or not after_deps - hass.config.components:
|
||||
domains_to_load.add(domain)
|
||||
|
||||
if not domains_to_load or domains_to_load == last_load:
|
||||
@@ -353,10 +361,9 @@ async def _async_set_up_integrations(
|
||||
|
||||
_LOGGER.debug("Setting up %s", domains_to_load)
|
||||
|
||||
await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in domains_to_load
|
||||
))
|
||||
await asyncio.gather(
|
||||
*(async_setup_component(hass, domain, config) for domain in domains_to_load)
|
||||
)
|
||||
|
||||
last_load = domains_to_load
|
||||
stage_2_domains -= domains_to_load
|
||||
@@ -366,10 +373,9 @@ async def _async_set_up_integrations(
|
||||
if stage_2_domains:
|
||||
_LOGGER.debug("Final set up: %s", stage_2_domains)
|
||||
|
||||
await asyncio.gather(*(
|
||||
async_setup_component(hass, domain, config)
|
||||
for domain in stage_2_domains
|
||||
))
|
||||
await asyncio.gather(
|
||||
*(async_setup_component(hass, domain, config) for domain in stage_2_domains)
|
||||
)
|
||||
|
||||
# Wrap up startup
|
||||
await hass.async_block_till_done()
|
||||
|
||||
Reference in New Issue
Block a user