From c481fdb7d062bbf07d87dff9cc4baeef7d16faea Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 23 Oct 2023 20:33:08 +0200 Subject: [PATCH] Rename safe mode to recovery mode (#102580) --- homeassistant/__main__.py | 6 +++-- homeassistant/bootstrap.py | 22 +++++++++---------- homeassistant/components/frontend/__init__.py | 6 ++--- homeassistant/components/http/__init__.py | 6 ++--- homeassistant/components/lovelace/__init__.py | 2 +- .../components/lovelace/dashboard.py | 10 ++++----- homeassistant/core.py | 6 ++--- homeassistant/helpers/check_config.py | 4 ++-- homeassistant/loader.py | 4 ++-- homeassistant/runner.py | 2 +- tests/components/frontend/test_init.py | 8 +++---- tests/components/http/test_init.py | 16 +++++++------- tests/components/lovelace/test_dashboard.py | 4 ++-- tests/helpers/test_check_config.py | 12 +++++----- tests/test_bootstrap.py | 14 ++++++------ tests/test_core.py | 4 ++-- tests/test_loader.py | 6 ++--- 17 files changed, 67 insertions(+), 65 deletions(-) diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index 9e4afa018a6..9acf46dbac6 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -93,7 +93,9 @@ def get_arguments() -> argparse.Namespace: help="Directory that contains the Home Assistant configuration", ) parser.add_argument( - "--safe-mode", action="store_true", help="Start Home Assistant in safe mode" + "--recovery-mode", + action="store_true", + help="Start Home Assistant in recovery mode", ) parser.add_argument( "--debug", action="store_true", help="Start Home Assistant in debug mode" @@ -193,7 +195,7 @@ def main() -> int: log_no_color=args.log_no_color, skip_pip=args.skip_pip, skip_pip_packages=args.skip_pip_packages, - safe_mode=args.safe_mode, + recovery_mode=args.recovery_mode, debug=args.debug, open_ui=args.open_ui, ) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 81ae4eb6e18..7f6c29d8105 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -137,14 +137,14 @@ async def async_setup_hass( config_dict = None basic_setup_success = False - if not (safe_mode := runtime_config.safe_mode): + if not (recovery_mode := runtime_config.recovery_mode): await hass.async_add_executor_job(conf_util.process_ha_config_upgrade, hass) try: config_dict = await conf_util.async_hass_config_yaml(hass) except HomeAssistantError as err: _LOGGER.error( - "Failed to parse configuration.yaml: %s. Activating safe mode", + "Failed to parse configuration.yaml: %s. Activating recovery mode", err, ) else: @@ -156,24 +156,24 @@ async def async_setup_hass( ) if config_dict is None: - safe_mode = True + recovery_mode = True elif not basic_setup_success: - _LOGGER.warning("Unable to set up core integrations. Activating safe mode") - safe_mode = True + _LOGGER.warning("Unable to set up core integrations. Activating recovery mode") + recovery_mode = True elif ( "frontend" in hass.data.get(DATA_SETUP, {}) and "frontend" not in hass.config.components ): - _LOGGER.warning("Detected that frontend did not load. Activating safe mode") + _LOGGER.warning("Detected that frontend did not load. Activating recovery mode") # Ask integrations to shut down. It's messy but we can't # do a clean stop without knowing what is broken with contextlib.suppress(asyncio.TimeoutError): async with hass.timeout.async_timeout(10): await hass.async_stop() - safe_mode = True + recovery_mode = True old_config = hass.config old_logging = hass.data.get(DATA_LOGGING) @@ -187,9 +187,9 @@ async def async_setup_hass( # Setup loader cache after the config dir has been set loader.async_setup(hass) - if safe_mode: - _LOGGER.info("Starting in safe mode") - hass.config.safe_mode = True + if recovery_mode: + _LOGGER.info("Starting in recovery mode") + hass.config.recovery_mode = True http_conf = (await http.async_get_last_config(hass)) or {} @@ -471,7 +471,7 @@ def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]: domains = {key.partition(" ")[0] for key in config if key != core.DOMAIN} # Add config entry domains - if not hass.config.safe_mode: + if not hass.config.recovery_mode: domains.update(hass.config_entries.async_domains()) # Make sure the Hass.io component is loaded diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 98b6f0331b5..e8a71d23adf 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -658,18 +658,18 @@ def websocket_get_themes( hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] ) -> None: """Handle get themes command.""" - if hass.config.safe_mode: + if hass.config.recovery_mode: connection.send_message( websocket_api.result_message( msg["id"], { "themes": { - "safe_mode": { + "recovery_mode": { "primary-color": "#db4437", "accent-color": "#ffca28", } }, - "default_theme": "safe_mode", + "default_theme": "recovery_mode", }, ) ) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 409b78fb16a..122b7b79ce9 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -445,7 +445,7 @@ class HomeAssistantHTTP: context = ssl_util.server_context_modern() context.load_cert_chain(self.ssl_certificate, self.ssl_key) except OSError as error: - if not self.hass.config.safe_mode: + if not self.hass.config.recovery_mode: raise HomeAssistantError( f"Could not use SSL certificate from {self.ssl_certificate}:" f" {error}" @@ -465,7 +465,7 @@ class HomeAssistantHTTP: context = None else: _LOGGER.critical( - "Home Assistant is running in safe mode with an emergency self" + "Home Assistant is running in recovery mode with an emergency self" " signed ssl certificate because the configured SSL certificate was" " not usable" ) @@ -572,7 +572,7 @@ async def start_http_server_and_save_config( """Startup the http server and save the config.""" await server.start() - # If we are set up successful, we store the HTTP settings for safe mode. + # If we are set up successful, we store the HTTP settings for recovery mode. store: storage.Store[dict[str, Any]] = storage.Store( hass, STORAGE_VERSION, STORAGE_KEY ) diff --git a/homeassistant/components/lovelace/__init__.py b/homeassistant/components/lovelace/__init__.py index 1412aa085c8..2c425bec785 100644 --- a/homeassistant/components/lovelace/__init__.py +++ b/homeassistant/components/lovelace/__init__.py @@ -144,7 +144,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: "yaml_dashboards": config[DOMAIN].get(CONF_DASHBOARDS, {}), } - if hass.config.safe_mode: + if hass.config.recovery_mode: return True async def storage_dashboard_changed(change_type, item_id, item): diff --git a/homeassistant/components/lovelace/dashboard.py b/homeassistant/components/lovelace/dashboard.py index 054aaf9b24c..e1641451221 100644 --- a/homeassistant/components/lovelace/dashboard.py +++ b/homeassistant/components/lovelace/dashboard.py @@ -114,7 +114,7 @@ class LovelaceStorage(LovelaceConfig): async def async_load(self, force): """Load config.""" - if self.hass.config.safe_mode: + if self.hass.config.recovery_mode: raise ConfigNotFound if self._data is None: @@ -127,8 +127,8 @@ class LovelaceStorage(LovelaceConfig): async def async_save(self, config): """Save config.""" - if self.hass.config.safe_mode: - raise HomeAssistantError("Saving not supported in safe mode") + if self.hass.config.recovery_mode: + raise HomeAssistantError("Saving not supported in recovery mode") if self._data is None: await self._load() @@ -138,8 +138,8 @@ class LovelaceStorage(LovelaceConfig): async def async_delete(self): """Delete config.""" - if self.hass.config.safe_mode: - raise HomeAssistantError("Deleting not supported in safe mode") + if self.hass.config.recovery_mode: + raise HomeAssistantError("Deleting not supported in recovery mode") await self._store.async_remove() self._data = None diff --git a/homeassistant/core.py b/homeassistant/core.py index 2cc79e5bbb4..e495973440e 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -2129,8 +2129,8 @@ class Config: # Dictionary of Media folders that integrations may use self.media_dirs: dict[str, str] = {} - # If Home Assistant is running in safe mode - self.safe_mode: bool = False + # If Home Assistant is running in recovery mode + self.recovery_mode: bool = False # Use legacy template behavior self.legacy_templates: bool = False @@ -2208,7 +2208,7 @@ class Config: "allowlist_external_urls": self.allowlist_external_urls, "version": __version__, "config_source": self.config_source, - "safe_mode": self.safe_mode, + "recovery_mode": self.recovery_mode, "state": self.hass.state.value, "external_url": self.external_url, "internal_url": self.internal_url, diff --git a/homeassistant/helpers/check_config.py b/homeassistant/helpers/check_config.py index 1e1cac050f1..3218c1e839b 100644 --- a/homeassistant/helpers/check_config.py +++ b/homeassistant/helpers/check_config.py @@ -127,7 +127,7 @@ async def async_check_ha_config_file( # noqa: C901 try: integration = await async_get_integration_with_requirements(hass, domain) except loader.IntegrationNotFound as ex: - if not hass.config.safe_mode: + if not hass.config.recovery_mode: result.add_error(f"Integration error: {domain} - {ex}") continue except RequirementsNotFound as ex: @@ -216,7 +216,7 @@ async def async_check_ha_config_file( # noqa: C901 ) platform = p_integration.get_platform(domain) except loader.IntegrationNotFound as ex: - if not hass.config.safe_mode: + if not hass.config.recovery_mode: result.add_error(f"Platform error {domain}.{p_name} - {ex}") continue except ( diff --git a/homeassistant/loader.py b/homeassistant/loader.py index 6107150cebb..e4f36f11a36 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -188,7 +188,7 @@ async def _async_get_custom_components( hass: HomeAssistant, ) -> dict[str, Integration]: """Return list of custom integrations.""" - if hass.config.safe_mode: + if hass.config.recovery_mode: return {} try: @@ -1179,7 +1179,7 @@ def _async_mount_config_dir(hass: HomeAssistant) -> None: def _lookup_path(hass: HomeAssistant) -> list[str]: """Return the lookup paths for legacy lookups.""" - if hass.config.safe_mode: + if hass.config.recovery_mode: return [PACKAGE_BUILTIN] return [PACKAGE_CUSTOM_COMPONENTS, PACKAGE_BUILTIN] diff --git a/homeassistant/runner.py b/homeassistant/runner.py index 10521f80135..ca658c154a2 100644 --- a/homeassistant/runner.py +++ b/homeassistant/runner.py @@ -43,7 +43,7 @@ class RuntimeConfig: config_dir: str skip_pip: bool = False skip_pip_packages: list[str] = dataclasses.field(default_factory=list) - safe_mode: bool = False + recovery_mode: bool = False verbose: bool = False diff --git a/tests/components/frontend/test_init.py b/tests/components/frontend/test_init.py index 721f6416154..f0c433f2e96 100644 --- a/tests/components/frontend/test_init.py +++ b/tests/components/frontend/test_init.py @@ -177,14 +177,14 @@ async def test_themes_api(hass: HomeAssistant, themes_ws_client) -> None: assert msg["result"]["default_dark_theme"] is None assert msg["result"]["themes"] == MOCK_THEMES - # safe mode - hass.config.safe_mode = True + # recovery mode + hass.config.recovery_mode = True await themes_ws_client.send_json({"id": 6, "type": "frontend/get_themes"}) msg = await themes_ws_client.receive_json() - assert msg["result"]["default_theme"] == "safe_mode" + assert msg["result"]["default_theme"] == "recovery_mode" assert msg["result"]["themes"] == { - "safe_mode": {"primary-color": "#db4437", "accent-color": "#ffca28"} + "recovery_mode": {"primary-color": "#db4437", "accent-color": "#ffca28"} } diff --git a/tests/components/http/test_init.py b/tests/components/http/test_init.py index 3fc8d7689d6..5a5bffe6748 100644 --- a/tests/components/http/test_init.py +++ b/tests/components/http/test_init.py @@ -289,7 +289,7 @@ async def test_emergency_ssl_certificate_when_invalid( _setup_broken_ssl_pem_files, tmp_path ) - hass.config.safe_mode = True + hass.config.recovery_mode = True assert ( await async_setup_component( hass, @@ -304,17 +304,17 @@ async def test_emergency_ssl_certificate_when_invalid( await hass.async_start() await hass.async_block_till_done() assert ( - "Home Assistant is running in safe mode with an emergency self signed ssl certificate because the configured SSL certificate was not usable" + "Home Assistant is running in recovery mode with an emergency self signed ssl certificate because the configured SSL certificate was not usable" in caplog.text ) assert hass.http.site is not None -async def test_emergency_ssl_certificate_not_used_when_not_safe_mode( +async def test_emergency_ssl_certificate_not_used_when_not_recovery_mode( hass: HomeAssistant, tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: - """Test an emergency cert is only used in safe mode.""" + """Test an emergency cert is only used in recovery mode.""" cert_path, key_path = await hass.async_add_executor_job( _setup_broken_ssl_pem_files, tmp_path @@ -338,7 +338,7 @@ async def test_emergency_ssl_certificate_when_invalid_get_url_fails( cert_path, key_path = await hass.async_add_executor_job( _setup_broken_ssl_pem_files, tmp_path ) - hass.config.safe_mode = True + hass.config.recovery_mode = True with patch( "homeassistant.components.http.get_url", side_effect=NoURLAvailableError @@ -358,7 +358,7 @@ async def test_emergency_ssl_certificate_when_invalid_get_url_fails( assert len(mock_get_url.mock_calls) == 1 assert ( - "Home Assistant is running in safe mode with an emergency self signed ssl certificate because the configured SSL certificate was not usable" + "Home Assistant is running in recovery mode with an emergency self signed ssl certificate because the configured SSL certificate was not usable" in caplog.text ) @@ -373,7 +373,7 @@ async def test_invalid_ssl_and_cannot_create_emergency_cert( cert_path, key_path = await hass.async_add_executor_job( _setup_broken_ssl_pem_files, tmp_path ) - hass.config.safe_mode = True + hass.config.recovery_mode = True with patch( "homeassistant.components.http.x509.CertificateBuilder", side_effect=OSError @@ -410,7 +410,7 @@ async def test_invalid_ssl_and_cannot_create_emergency_cert_with_ssl_peer_cert( cert_path, key_path = await hass.async_add_executor_job( _setup_broken_ssl_pem_files, tmp_path ) - hass.config.safe_mode = True + hass.config.recovery_mode = True with patch( "homeassistant.components.http.x509.CertificateBuilder", side_effect=OSError diff --git a/tests/components/lovelace/test_dashboard.py b/tests/components/lovelace/test_dashboard.py index 8663ec0fc11..05bc7f372b8 100644 --- a/tests/components/lovelace/test_dashboard.py +++ b/tests/components/lovelace/test_dashboard.py @@ -48,8 +48,8 @@ async def test_lovelace_from_storage( assert response["result"] == {"yo": "hello"} - # Test with safe mode - hass.config.safe_mode = True + # Test with recovery mode + hass.config.recovery_mode = True await client.send_json({"id": 8, "type": "lovelace/config"}) response = await client.receive_json() assert not response["success"] diff --git a/tests/helpers/test_check_config.py b/tests/helpers/test_check_config.py index 3b9b3cf6558..6af03136760 100644 --- a/tests/helpers/test_check_config.py +++ b/tests/helpers/test_check_config.py @@ -112,11 +112,11 @@ async def test_component_requirement_not_found(hass: HomeAssistant) -> None: assert not res.errors -async def test_component_not_found_safe_mode(hass: HomeAssistant) -> None: - """Test no errors if component not found in safe mode.""" +async def test_component_not_found_recovery_mode(hass: HomeAssistant) -> None: + """Test no errors if component not found in recovery mode.""" # Make sure they don't exist files = {YAML_CONFIG_FILE: BASE_CONFIG + "beer:"} - hass.config.safe_mode = True + hass.config.recovery_mode = True with patch("os.path.isfile", return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) log_ha_config(res) @@ -145,11 +145,11 @@ async def test_component_platform_not_found_2(hass: HomeAssistant) -> None: assert not res.errors -async def test_platform_not_found_safe_mode(hass: HomeAssistant) -> None: - """Test no errors if platform not found in safe_mode.""" +async def test_platform_not_found_recovery_mode(hass: HomeAssistant) -> None: + """Test no errors if platform not found in recovery_mode.""" # Make sure they don't exist files = {YAML_CONFIG_FILE: BASE_CONFIG + "light:\n platform: beer"} - hass.config.safe_mode = True + hass.config.recovery_mode = True with patch("os.path.isfile", return_value=True), patch_yaml_files(files): res = await async_check_ha_config_file(hass) log_ha_config(res) diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index ea9e04ac993..6938acb9cc9 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -488,7 +488,7 @@ async def test_setup_hass( log_file=log_file, log_no_color=log_no_color, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) @@ -547,7 +547,7 @@ async def test_setup_hass_takes_longer_than_log_slow_startup( log_file=log_file, log_no_color=log_no_color, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) @@ -574,7 +574,7 @@ async def test_setup_hass_invalid_yaml( log_file="", log_no_color=False, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) @@ -602,7 +602,7 @@ async def test_setup_hass_config_dir_nonexistent( log_file="", log_no_color=False, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) is None @@ -630,7 +630,7 @@ async def test_setup_hass_safe_mode( log_file="", log_no_color=False, skip_pip=True, - safe_mode=True, + recovery_mode=True, ), ) @@ -661,7 +661,7 @@ async def test_setup_hass_invalid_core_config( log_file="", log_no_color=False, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) @@ -704,7 +704,7 @@ async def test_setup_safe_mode_if_no_frontend( log_file=log_file, log_no_color=log_no_color, skip_pip=True, - safe_mode=False, + recovery_mode=False, ), ) diff --git a/tests/test_core.py b/tests/test_core.py index ed6823d2bd1..cd855ab2c73 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1449,7 +1449,7 @@ async def test_config_defaults() -> None: assert config.allowlist_external_dirs == set() assert config.allowlist_external_urls == set() assert config.media_dirs == {} - assert config.safe_mode is False + assert config.recovery_mode is False assert config.legacy_templates is False assert config.currency == "EUR" assert config.country is None @@ -1487,7 +1487,7 @@ async def test_config_as_dict() -> None: "allowlist_external_urls": set(), "version": __version__, "config_source": ha.ConfigSource.DEFAULT, - "safe_mode": False, + "recovery_mode": False, "state": "RUNNING", "external_url": None, "internal_url": None, diff --git a/tests/test_loader.py b/tests/test_loader.py index 3c95111db3a..7959ddb4684 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -690,9 +690,9 @@ async def test_get_mqtt(hass: HomeAssistant) -> None: assert mqtt["test_2"] == ["test_2/discovery"] -async def test_get_custom_components_safe_mode(hass: HomeAssistant) -> None: - """Test that we get empty custom components in safe mode.""" - hass.config.safe_mode = True +async def test_get_custom_components_recovery_mode(hass: HomeAssistant) -> None: + """Test that we get empty custom components in recovery mode.""" + hass.config.recovery_mode = True assert await loader.async_get_custom_components(hass) == {}