async def async_from_config_dict( config: ConfigType, opp: core.OpenPeerPower) -> core.OpenPeerPower | None: """Try to configure Open Peer Power from a configuration dictionary. Dynamically loads required components and its dependencies. This method is a coroutine. """ start = monotonic() opp.config_entries = config_entries.ConfigEntries(opp, config) await opp.config_entries.async_initialize() # Set up core. _LOGGER.debug("Setting up %s", CORE_INTEGRATIONS) if not all(await asyncio.gather(*(async_setup_component(opp, domain, config) for domain in CORE_INTEGRATIONS))): _LOGGER.error("Open Peer Power core failed to initialize. ") return None _LOGGER.debug("Open Peer Power core initialized") core_config = config.get(core.DOMAIN, {}) try: await conf_util.async_process_op_core_config(opp, core_config) except vol.Invalid as config_err: conf_util.async_log_exception(config_err, "openpeerpower", core_config, opp) return None except OpenPeerPowerError: _LOGGER.error("Open Peer Power core failed to initialize. " "Further initialization aborted") return None await _async_set_up_integrations(opp, config) stop = monotonic() _LOGGER.info("Open Peer Power initialized in %.2fs", stop - start) if REQUIRED_NEXT_PYTHON_DATE and sys.version_info[: 3] < REQUIRED_NEXT_PYTHON_VER: msg = ( "Support for the running Python version " f"{'.'.join(str(x) for x in sys.version_info[:3])} is deprecated and will " f"be removed in the first release after {REQUIRED_NEXT_PYTHON_DATE}. " "Please upgrade Python to " f"{'.'.join(str(x) for x in REQUIRED_NEXT_PYTHON_VER)} or " "higher.") _LOGGER.warning(msg) opp.components.persistent_notification.async_create( msg, "Python version", "python_version") return opp
async def async_validate_config(opp, config): """Validate config.""" if DOMAIN not in config: return config config_sections = [] for cfg in cv.ensure_list(config[DOMAIN]): try: cfg = CONFIG_SECTION_SCHEMA(cfg) if CONF_TRIGGER in cfg: cfg[CONF_TRIGGER] = await async_validate_trigger_config( opp, cfg[CONF_TRIGGER]) except vol.Invalid as err: async_log_exception(err, DOMAIN, cfg, opp) continue legacy_warn_printed = False for old_key, new_key, transform in ( ( CONF_SENSORS, SENSOR_DOMAIN, sensor_platform.rewrite_legacy_to_modern_conf, ), ( CONF_BINARY_SENSORS, BINARY_SENSOR_DOMAIN, binary_sensor_platform.rewrite_legacy_to_modern_conf, ), ): if old_key not in cfg: continue if not legacy_warn_printed: legacy_warn_printed = True logging.getLogger(__name__).warning( "The entity definition format under template: differs from the platform " "configuration format. See " "https://www.openpeerpower.io/integrations/template#configuration-for-trigger-based-template-sensors" ) definitions = list(cfg[new_key]) if new_key in cfg else [] definitions.extend(transform(cfg[old_key])) cfg = {**cfg, new_key: definitions} config_sections.append(cfg) # Create a copy of the configuration with all config for current # component removed and add validated config back in. config = config_without_domain(config, DOMAIN) config[DOMAIN] = config_sections return config
async def _try_async_validate_config_item(opp, config, full_config=None): """Validate config item.""" try: config = await async_validate_config_item(opp, config, full_config) except ( vol.Invalid, OpenPeerPowerError, IntegrationNotFound, InvalidDeviceAutomationConfig, ) as ex: async_log_exception(ex, DOMAIN, full_config or config, opp) return None return config
async def async_load_config(path: str, opp: OpenPeerPowerType, consider_home: timedelta): """Load devices from YAML configuration file. This method is a coroutine. """ dev_schema = vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ICON, default=None): vol.Any(None, cv.icon), vol.Optional("track", default=False): cv.boolean, vol.Optional(CONF_MAC, default=None): vol.Any(None, vol.All(cv.string, vol.Upper)), vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, vol.Optional("gravatar", default=None): vol.Any(None, cv.string), vol.Optional("picture", default=None): vol.Any(None, cv.string), vol.Optional(CONF_CONSIDER_HOME, default=consider_home): vol.All(cv.time_period, cv.positive_timedelta), }) result = [] try: devices = await opp.async_add_job(load_yaml_config_file, path) except OpenPeerPowerError as err: LOGGER.error("Unable to load %s: %s", path, str(err)) return [] except FileNotFoundError: return [] for dev_id, device in devices.items(): # Deprecated option. We just ignore it to avoid breaking change device.pop("vendor", None) try: device = dev_schema(device) device["dev_id"] = cv.slugify(dev_id) except vol.Invalid as exp: async_log_exception(exp, dev_id, devices, opp) else: result.append(Device(opp, **device)) return result
async def _try_async_validate_config_item(opp, object_id, config, full_config=None): """Validate config item.""" raw_config = None with suppress(ValueError): # Invalid config raw_config = dict(config) try: cv.slug(object_id) config = await async_validate_config_item(opp, config, full_config) except (vol.Invalid, OpenPeerPowerError) as ex: async_log_exception(ex, DOMAIN, full_config or config, opp) return None if isinstance(config, BlueprintInputs): return config config = ScriptConfig(config) config.raw_config = raw_config return config