def check(config_dir, secrets=False): """Perform a check by mocking hass load functions.""" logging.getLogger("homeassistant.loader").setLevel(logging.CRITICAL) res: Dict[str, Any] = { "yaml_files": OrderedDict(), # yaml_files loaded "secrets": OrderedDict(), # secret cache and secrets loaded "except": OrderedDict(), # exceptions raised (with config) #'components' is a HomeAssistantConfig # noqa: E265 "secret_cache": None, } # pylint: disable=possibly-unused-variable def mock_load(filename): """Mock hass.util.load_yaml to save config file names.""" res["yaml_files"][filename] = True return MOCKS["load"][1](filename) # pylint: disable=possibly-unused-variable def mock_secrets(ldr, node): """Mock _get_secrets.""" try: val = MOCKS["secrets"][1](ldr, node) except HomeAssistantError: val = None res["secrets"][node.value] = val return val # Patches to skip functions for sil in SILENCE: PATCHES[sil] = patch(sil) # Patches with local mock functions for key, val in MOCKS.items(): if not secrets and key == "secrets": continue # The * in the key is removed to find the mock_function (side_effect) # This allows us to use one side_effect to patch multiple locations mock_function = locals()[f"mock_{key.replace('*', '')}"] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches for pat in PATCHES.values(): pat.start() if secrets: # Ensure !secrets point to the patched function yaml_loader.yaml.SafeLoader.add_constructor("!secret", yaml_loader.secret_yaml) try: hass = core.HomeAssistant() hass.config.config_dir = config_dir res["components"] = hass.loop.run_until_complete( async_check_ha_config_file(hass)) res["secret_cache"] = OrderedDict(yaml_loader.__SECRET_CACHE) for err in res["components"].errors: domain = err.domain or ERROR_STR res["except"].setdefault(domain, []).append(err.message) if err.config: res["except"].setdefault(domain, []).append(err.config) except Exception as err: # pylint: disable=broad-except _LOGGER.exception("BURB") print(color("red", "Fatal error while loading config:"), str(err)) res["except"].setdefault(ERROR_STR, []).append(str(err)) finally: # Stop all patches for pat in PATCHES.values(): pat.stop() if secrets: # Ensure !secrets point to the original function yaml_loader.yaml.SafeLoader.add_constructor( "!secret", yaml_loader.secret_yaml) bootstrap.clear_secret_cache() return res
def check(config_path): """Perform a check by mocking hass load functions.""" res = { 'yaml_files': OrderedDict(), # yaml_files loaded 'secrets': OrderedDict(), # secret cache and secrets loaded 'except': OrderedDict(), # exceptions raised (with config) 'components': OrderedDict(), # successful components 'secret_cache': OrderedDict(), } # pylint: disable=unused-variable def mock_load(filename): """Mock hass.util.load_yaml to save config files.""" res['yaml_files'][filename] = True return MOCKS['load'][1](filename) # pylint: disable=unused-variable def mock_get(comp_name): """Mock hass.loader.get_component to replace setup & setup_platform.""" def mock_setup(*kwargs): """Mock setup, only record the component name & config.""" assert comp_name not in res['components'], \ "Components should contain a list of platforms" res['components'][comp_name] = kwargs[1].get(comp_name) return True module = MOCKS['get'][1](comp_name) if module is None: # Ensure list res['except'][ERROR_STR] = res['except'].get(ERROR_STR, []) res['except'][ERROR_STR].append('{} not found: {}'.format( 'Platform' if '.' in comp_name else 'Component', comp_name)) return None # Test if platform/component and overwrite setup if '.' in comp_name: module.setup_platform = mock_setup if hasattr(module, 'async_setup_platform'): del module.async_setup_platform else: module.setup = mock_setup if hasattr(module, 'async_setup'): del module.async_setup return module # pylint: disable=unused-variable def mock_secrets(ldr, node): """Mock _get_secrets.""" try: val = MOCKS['secrets'][1](ldr, node) except HomeAssistantError: val = None res['secrets'][node.value] = val return val def mock_except(ex, domain, config, # pylint: disable=unused-variable hass=None): """Mock bootstrap.log_exception.""" MOCKS['except'][1](ex, domain, config, hass) res['except'][domain] = config.get(domain, config) # Patches to skip functions for sil in SILENCE: PATCHES[sil] = patch(sil) # Patches with local mock functions for key, val in MOCKS.items(): # The * in the key is removed to find the mock_function (side_effect) # This allows us to use one side_effect to patch multiple locations mock_function = locals()['mock_' + key.replace('*', '')] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches for pat in PATCHES.values(): pat.start() # Ensure !secrets point to the patched function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) try: bootstrap.from_config_file(config_path, skip_pip=True) res['secret_cache'] = dict(yaml.__SECRET_CACHE) except Exception as err: # pylint: disable=broad-except print(color('red', 'Fatal error while loading config:'), str(err)) finally: # Stop all patches for pat in PATCHES.values(): pat.stop() # Ensure !secrets point to the original function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) bootstrap.clear_secret_cache() return res
def check(config_dir, secrets=False): """Perform a check by mocking hass load functions.""" logging.getLogger('homeassistant.loader').setLevel(logging.CRITICAL) res = { 'yaml_files': OrderedDict(), # yaml_files loaded 'secrets': OrderedDict(), # secret cache and secrets loaded 'except': OrderedDict(), # exceptions raised (with config) 'components': None, # successful components 'secret_cache': None, } # pylint: disable=possibly-unused-variable def mock_load(filename): """Mock hass.util.load_yaml to save config file names.""" res['yaml_files'][filename] = True return MOCKS['load'][1](filename) # pylint: disable=possibly-unused-variable def mock_secrets(ldr, node): """Mock _get_secrets.""" try: val = MOCKS['secrets'][1](ldr, node) except HomeAssistantError: val = None res['secrets'][node.value] = val return val # Patches to skip functions for sil in SILENCE: PATCHES[sil] = patch(sil) # Patches with local mock functions for key, val in MOCKS.items(): if not secrets and key == 'secrets': continue # The * in the key is removed to find the mock_function (side_effect) # This allows us to use one side_effect to patch multiple locations mock_function = locals()['mock_' + key.replace('*', '')] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches for pat in PATCHES.values(): pat.start() if secrets: # Ensure !secrets point to the patched function yaml.yaml.SafeLoader.add_constructor('!secret', yaml.secret_yaml) try: hass = core.HomeAssistant() hass.config.config_dir = config_dir res['components'] = check_ha_config_file(hass) res['secret_cache'] = OrderedDict(yaml.__SECRET_CACHE) for err in res['components'].errors: domain = err.domain or ERROR_STR res['except'].setdefault(domain, []).append(err.message) if err.config: res['except'].setdefault(domain, []).append(err.config) except Exception as err: # pylint: disable=broad-except _LOGGER.exception("BURB") print(color('red', 'Fatal error while loading config:'), str(err)) res['except'].setdefault(ERROR_STR, []).append(str(err)) finally: # Stop all patches for pat in PATCHES.values(): pat.stop() if secrets: # Ensure !secrets point to the original function yaml.yaml.SafeLoader.add_constructor('!secret', yaml.secret_yaml) bootstrap.clear_secret_cache() return res
def check(config_path): """Perform a check by mocking hass load functions.""" res = { 'yaml_files': OrderedDict(), # yaml_files loaded 'secrets': OrderedDict(), # secret cache and secrets loaded 'except': OrderedDict(), # exceptions raised (with config) 'components': OrderedDict(), # successful components 'secret_cache': OrderedDict(), } # pylint: disable=unused-variable def mock_load(filename): """Mock hass.util.load_yaml to save config files.""" res['yaml_files'][filename] = True return MOCKS['load'][1](filename) # pylint: disable=unused-variable def mock_get(comp_name): """Mock hass.loader.get_component to replace setup & setup_platform.""" def mock_setup(*kwargs): """Mock setup, only record the component name & config.""" assert comp_name not in res['components'], \ "Components should contain a list of platforms" res['components'][comp_name] = kwargs[1].get(comp_name) return True module = MOCKS['get'][1](comp_name) if module is None: # Ensure list msg = '{} not found: {}'.format( 'Platform' if '.' in comp_name else 'Component', comp_name) res['except'].setdefault(ERROR_STR, []).append(msg) return None # Test if platform/component and overwrite setup if '.' in comp_name: module.setup_platform = mock_setup if hasattr(module, 'async_setup_platform'): del module.async_setup_platform else: module.setup = mock_setup if hasattr(module, 'async_setup'): del module.async_setup return module # pylint: disable=unused-variable def mock_secrets(ldr, node): """Mock _get_secrets.""" try: val = MOCKS['secrets'][1](ldr, node) except HomeAssistantError: val = None res['secrets'][node.value] = val return val def mock_except( ex, domain, config, # pylint: disable=unused-variable hass=None): """Mock config.log_exception.""" MOCKS['except'][1](ex, domain, config, hass) res['except'][domain] = config.get(domain, config) def mock_package_error( # pylint: disable=unused-variable package, component, config, message): """Mock config_util._log_pkg_error.""" MOCKS['package_error'][1](package, component, config, message) pkg_key = 'homeassistant.packages.{}'.format(package) res['except'][pkg_key] = config.get('homeassistant', {}) \ .get('packages', {}).get(package) def mock_logger_exception(msg, *params): """Log logger.exceptions.""" res['except'].setdefault(ERROR_STR, []).append(msg % params) MOCKS['logger_exception'][1](msg, *params) # Patches to skip functions for sil in SILENCE: PATCHES[sil] = patch(sil) # Patches with local mock functions for key, val in MOCKS.items(): # The * in the key is removed to find the mock_function (side_effect) # This allows us to use one side_effect to patch multiple locations mock_function = locals()['mock_' + key.replace('*', '')] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches for pat in PATCHES.values(): pat.start() # Ensure !secrets point to the patched function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) try: with patch('homeassistant.util.logging.AsyncHandler._process'): bootstrap.from_config_file(config_path, skip_pip=True) res['secret_cache'] = dict(yaml.__SECRET_CACHE) except Exception as err: # pylint: disable=broad-except print(color('red', 'Fatal error while loading config:'), str(err)) res['except'].setdefault(ERROR_STR, []).append(err) finally: # Stop all patches for pat in PATCHES.values(): pat.stop() # Ensure !secrets point to the original function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) bootstrap.clear_secret_cache() return res
def check(config_dir, secrets=False): """Perform a check by mocking hass load functions.""" logging.getLogger('homeassistant.loader').setLevel(logging.CRITICAL) res = { 'yaml_files': OrderedDict(), # yaml_files loaded 'secrets': OrderedDict(), # secret cache and secrets loaded 'except': OrderedDict(), # exceptions raised (with config) 'components': None, # successful components 'secret_cache': None, } # pylint: disable=unused-variable def mock_load(filename): """Mock hass.util.load_yaml to save config file names.""" res['yaml_files'][filename] = True return MOCKS['load'][1](filename) # pylint: disable=unused-variable def mock_secrets(ldr, node): """Mock _get_secrets.""" try: val = MOCKS['secrets'][1](ldr, node) except HomeAssistantError: val = None res['secrets'][node.value] = val return val # Patches to skip functions for sil in SILENCE: PATCHES[sil] = patch(sil) # Patches with local mock functions for key, val in MOCKS.items(): if not secrets and key == 'secrets': continue # The * in the key is removed to find the mock_function (side_effect) # This allows us to use one side_effect to patch multiple locations mock_function = locals()['mock_' + key.replace('*', '')] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches for pat in PATCHES.values(): pat.start() if secrets: # Ensure !secrets point to the patched function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) try: class HassConfig(): """Hass object with config.""" def __init__(self, conf_dir): """Init the config_dir.""" self.config = core.Config() self.config.config_dir = conf_dir loader.prepare(HassConfig(config_dir)) res['components'] = check_ha_config_file(config_dir) res['secret_cache'] = OrderedDict(yaml.__SECRET_CACHE) for err in res['components'].errors: domain = err.domain or ERROR_STR res['except'].setdefault(domain, []).append(err.message) if err.config: res['except'].setdefault(domain, []).append(err.config) except Exception as err: # pylint: disable=broad-except print(color('red', 'Fatal error while loading config:'), str(err)) res['except'].setdefault(ERROR_STR, []).append(str(err)) finally: # Stop all patches for pat in PATCHES.values(): pat.stop() if secrets: # Ensure !secrets point to the original function yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) bootstrap.clear_secret_cache() return res