Don't allow hass.config.config_dir to be None (#98442)
parent
5ed3e90607
commit
91faa53843
|
@ -110,8 +110,7 @@ async def async_setup_hass(
|
|||
runtime_config: RuntimeConfig,
|
||||
) -> core.HomeAssistant | None:
|
||||
"""Set up Home Assistant."""
|
||||
hass = core.HomeAssistant()
|
||||
hass.config.config_dir = runtime_config.config_dir
|
||||
hass = core.HomeAssistant(runtime_config.config_dir)
|
||||
|
||||
async_enable_logging(
|
||||
hass,
|
||||
|
@ -178,14 +177,13 @@ async def async_setup_hass(
|
|||
old_config = hass.config
|
||||
old_logging = hass.data.get(DATA_LOGGING)
|
||||
|
||||
hass = core.HomeAssistant()
|
||||
hass = core.HomeAssistant(old_config.config_dir)
|
||||
if old_logging:
|
||||
hass.data[DATA_LOGGING] = old_logging
|
||||
hass.config.skip_pip = old_config.skip_pip
|
||||
hass.config.skip_pip_packages = old_config.skip_pip_packages
|
||||
hass.config.internal_url = old_config.internal_url
|
||||
hass.config.external_url = old_config.external_url
|
||||
hass.config.config_dir = old_config.config_dir
|
||||
# Setup loader cache after the config dir has been set
|
||||
loader.async_setup(hass)
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ class CloudClient(Interface):
|
|||
@property
|
||||
def base_path(self) -> Path:
|
||||
"""Return path to base dir."""
|
||||
assert self._hass.config.config_dir is not None
|
||||
return Path(self._hass.config.config_dir)
|
||||
|
||||
@property
|
||||
|
|
|
@ -51,9 +51,6 @@ class FileNotificationService(BaseNotificationService):
|
|||
def send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||
"""Send a message to a file."""
|
||||
file: TextIO
|
||||
if not self.hass.config.config_dir:
|
||||
return
|
||||
|
||||
filepath: str = os.path.join(self.hass.config.config_dir, self.filename)
|
||||
with open(filepath, "a", encoding="utf8") as file:
|
||||
if os.stat(filepath).st_size == 0:
|
||||
|
|
|
@ -286,7 +286,7 @@ async def _set_active_climate_profile(
|
|||
async def _async_dump_hap_config(hass: HomeAssistant, service: ServiceCall) -> None:
|
||||
"""Service to dump the configuration of a Homematic IP Access Point."""
|
||||
config_path: str = (
|
||||
service.data.get(ATTR_CONFIG_OUTPUT_PATH) or hass.config.config_dir or "."
|
||||
service.data.get(ATTR_CONFIG_OUTPUT_PATH) or hass.config.config_dir
|
||||
)
|
||||
config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
|
||||
anonymize = service.data[ATTR_ANONYMIZE]
|
||||
|
|
|
@ -234,7 +234,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
|
||||
hass_path: str = HOMEASSISTANT_PATH[0]
|
||||
config_dir = hass.config.config_dir
|
||||
assert config_dir is not None
|
||||
paths_re = re.compile(
|
||||
r"(?:{})/(.*)".format("|".join([re.escape(x) for x in (hass_path, config_dir)]))
|
||||
)
|
||||
|
|
|
@ -36,7 +36,6 @@ async def async_setup_entry(
|
|||
VerisureSmartcam.capture_smartcam.__name__,
|
||||
)
|
||||
|
||||
assert hass.config.config_dir
|
||||
async_add_entities(
|
||||
VerisureSmartcam(coordinator, serial_number, hass.config.config_dir)
|
||||
for serial_number in coordinator.data["cameras"]
|
||||
|
|
|
@ -802,7 +802,6 @@ class LogRelayHandler(logging.Handler):
|
|||
|
||||
hass_path: str = HOMEASSISTANT_PATH[0]
|
||||
config_dir = self.hass.config.config_dir
|
||||
assert config_dir is not None
|
||||
paths_re = re.compile(
|
||||
r"(?:{})/(.*)".format(
|
||||
"|".join([re.escape(x) for x in (hass_path, config_dir)])
|
||||
|
|
|
@ -337,7 +337,6 @@ async def async_create_default_config(hass: HomeAssistant) -> bool:
|
|||
|
||||
Return if creation was successful.
|
||||
"""
|
||||
assert hass.config.config_dir
|
||||
return await hass.async_add_executor_job(
|
||||
_write_default_config, hass.config.config_dir
|
||||
)
|
||||
|
@ -390,10 +389,7 @@ async def async_hass_config_yaml(hass: HomeAssistant) -> dict:
|
|||
This function allow a component inside the asyncio loop to reload its
|
||||
configuration by itself. Include package merge.
|
||||
"""
|
||||
if hass.config.config_dir is None:
|
||||
secrets = None
|
||||
else:
|
||||
secrets = Secrets(Path(hass.config.config_dir))
|
||||
secrets = Secrets(Path(hass.config.config_dir))
|
||||
|
||||
# Not using async_add_executor_job because this is an internal method.
|
||||
config = await hass.loop.run_in_executor(
|
||||
|
|
|
@ -288,13 +288,13 @@ class HomeAssistant:
|
|||
http: HomeAssistantHTTP = None # type: ignore[assignment]
|
||||
config_entries: ConfigEntries = None # type: ignore[assignment]
|
||||
|
||||
def __new__(cls) -> HomeAssistant:
|
||||
def __new__(cls, config_dir: str) -> HomeAssistant:
|
||||
"""Set the _hass thread local data."""
|
||||
hass = super().__new__(cls)
|
||||
_hass.hass = hass
|
||||
return hass
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, config_dir: str) -> None:
|
||||
"""Initialize new Home Assistant object."""
|
||||
self.loop = asyncio.get_running_loop()
|
||||
self._tasks: set[asyncio.Future[Any]] = set()
|
||||
|
@ -302,7 +302,7 @@ class HomeAssistant:
|
|||
self.bus = EventBus(self)
|
||||
self.services = ServiceRegistry(self)
|
||||
self.states = StateMachine(self.bus, self.loop)
|
||||
self.config = Config(self)
|
||||
self.config = Config(self, config_dir)
|
||||
self.components = loader.Components(self)
|
||||
self.helpers = loader.Helpers(self)
|
||||
# This is a dictionary that any component can store any data on.
|
||||
|
@ -2011,7 +2011,7 @@ class ServiceRegistry:
|
|||
class Config:
|
||||
"""Configuration settings for Home Assistant."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
|
||||
"""Initialize a new config object."""
|
||||
self.hass = hass
|
||||
|
||||
|
@ -2047,7 +2047,7 @@ class Config:
|
|||
self.api: ApiConfig | None = None
|
||||
|
||||
# Directory that holds the configuration
|
||||
self.config_dir: str | None = None
|
||||
self.config_dir: str = config_dir
|
||||
|
||||
# List of allowed external dirs to access
|
||||
self.allowlist_external_dirs: set[str] = set()
|
||||
|
@ -2078,8 +2078,6 @@ class Config:
|
|||
|
||||
Async friendly.
|
||||
"""
|
||||
if self.config_dir is None:
|
||||
raise HomeAssistantError("config_dir is not set")
|
||||
return os.path.join(self.config_dir, *path)
|
||||
|
||||
def is_allowed_external_url(self, url: str) -> bool:
|
||||
|
|
|
@ -94,8 +94,6 @@ async def async_check_ha_config_file( # noqa: C901
|
|||
if not await hass.async_add_executor_job(os.path.isfile, config_path):
|
||||
return result.add_error("File configuration.yaml not found.")
|
||||
|
||||
assert hass.config.config_dir is not None
|
||||
|
||||
config = await hass.async_add_executor_job(
|
||||
load_yaml_config_file,
|
||||
config_path,
|
||||
|
|
|
@ -1148,17 +1148,13 @@ async def _async_component_dependencies(
|
|||
return loaded
|
||||
|
||||
|
||||
def _async_mount_config_dir(hass: HomeAssistant) -> bool:
|
||||
def _async_mount_config_dir(hass: HomeAssistant) -> None:
|
||||
"""Mount config dir in order to load custom_component.
|
||||
|
||||
Async friendly but not a coroutine.
|
||||
"""
|
||||
if hass.config.config_dir is None:
|
||||
_LOGGER.error("Can't load integrations - configuration directory is not set")
|
||||
return False
|
||||
if hass.config.config_dir not in sys.path:
|
||||
sys.path.insert(0, hass.config.config_dir)
|
||||
return True
|
||||
|
||||
|
||||
def _lookup_path(hass: HomeAssistant) -> list[str]:
|
||||
|
|
|
@ -50,8 +50,7 @@ def run(args):
|
|||
|
||||
async def run_command(args):
|
||||
"""Run the command."""
|
||||
hass = HomeAssistant()
|
||||
hass.config.config_dir = os.path.join(os.getcwd(), args.config)
|
||||
hass = HomeAssistant(os.path.join(os.getcwd(), args.config))
|
||||
hass.auth = await auth_manager_from_config(hass, [{"type": "homeassistant"}], [])
|
||||
provider = hass.auth.auth_providers[0]
|
||||
await provider.async_initialize()
|
||||
|
|
|
@ -49,7 +49,7 @@ def run(args):
|
|||
|
||||
async def run_benchmark(bench):
|
||||
"""Run a benchmark."""
|
||||
hass = core.HomeAssistant()
|
||||
hass = core.HomeAssistant("")
|
||||
runtime = await bench(hass)
|
||||
print(f"Benchmark {bench.__name__} done in {runtime}s")
|
||||
await hass.async_stop()
|
||||
|
|
|
@ -231,9 +231,8 @@ def check(config_dir, secrets=False):
|
|||
|
||||
async def async_check_config(config_dir):
|
||||
"""Check the HA config."""
|
||||
hass = core.HomeAssistant()
|
||||
hass = core.HomeAssistant(config_dir)
|
||||
loader.async_setup(hass)
|
||||
hass.config.config_dir = config_dir
|
||||
hass.config_entries = ConfigEntries(hass, {})
|
||||
await ar.async_load(hass)
|
||||
await dr.async_load(hass)
|
||||
|
|
|
@ -39,8 +39,7 @@ def run(args):
|
|||
|
||||
async def async_run(config_dir):
|
||||
"""Make sure config exists."""
|
||||
hass = HomeAssistant()
|
||||
hass.config.config_dir = config_dir
|
||||
hass = HomeAssistant(config_dir)
|
||||
path = await config_util.async_ensure_config_exists(hass)
|
||||
await hass.async_stop(force=True)
|
||||
return path
|
||||
|
|
|
@ -179,7 +179,7 @@ def get_test_home_assistant():
|
|||
|
||||
async def async_test_home_assistant(event_loop, load_registries=True):
|
||||
"""Return a Home Assistant object pointing at test config dir."""
|
||||
hass = HomeAssistant()
|
||||
hass = HomeAssistant(get_test_config_dir())
|
||||
store = auth_store.AuthStore(hass)
|
||||
hass.auth = auth.AuthManager(hass, store, {}, {})
|
||||
ensure_auth_manager_loaded(hass.auth)
|
||||
|
@ -231,7 +231,6 @@ async def async_test_home_assistant(event_loop, load_registries=True):
|
|||
hass.data[loader.DATA_CUSTOM_COMPONENTS] = {}
|
||||
|
||||
hass.config.location_name = "test home"
|
||||
hass.config.config_dir = get_test_config_dir()
|
||||
hass.config.latitude = 32.87336
|
||||
hass.config.longitude = -117.22743
|
||||
hass.config.elevation = 0
|
||||
|
|
|
@ -552,8 +552,8 @@ async def stop_hass(
|
|||
|
||||
created = []
|
||||
|
||||
def mock_hass():
|
||||
hass_inst = orig_hass()
|
||||
def mock_hass(*args):
|
||||
hass_inst = orig_hass(*args)
|
||||
created.append(hass_inst)
|
||||
return hass_inst
|
||||
|
||||
|
|
|
@ -1428,7 +1428,7 @@ async def test_serviceregistry_return_response_optional(
|
|||
async def test_config_defaults() -> None:
|
||||
"""Test config defaults."""
|
||||
hass = Mock()
|
||||
config = ha.Config(hass)
|
||||
config = ha.Config(hass, "/test/ha-config")
|
||||
assert config.hass is hass
|
||||
assert config.latitude == 0
|
||||
assert config.longitude == 0
|
||||
|
@ -1442,7 +1442,7 @@ async def test_config_defaults() -> None:
|
|||
assert config.skip_pip_packages == []
|
||||
assert config.components == set()
|
||||
assert config.api is None
|
||||
assert config.config_dir is None
|
||||
assert config.config_dir == "/test/ha-config"
|
||||
assert config.allowlist_external_dirs == set()
|
||||
assert config.allowlist_external_urls == set()
|
||||
assert config.media_dirs == {}
|
||||
|
@ -1455,22 +1455,19 @@ async def test_config_defaults() -> None:
|
|||
|
||||
async def test_config_path_with_file() -> None:
|
||||
"""Test get_config_path method."""
|
||||
config = ha.Config(None)
|
||||
config.config_dir = "/test/ha-config"
|
||||
config = ha.Config(None, "/test/ha-config")
|
||||
assert config.path("test.conf") == "/test/ha-config/test.conf"
|
||||
|
||||
|
||||
async def test_config_path_with_dir_and_file() -> None:
|
||||
"""Test get_config_path method."""
|
||||
config = ha.Config(None)
|
||||
config.config_dir = "/test/ha-config"
|
||||
config = ha.Config(None, "/test/ha-config")
|
||||
assert config.path("dir", "test.conf") == "/test/ha-config/dir/test.conf"
|
||||
|
||||
|
||||
async def test_config_as_dict() -> None:
|
||||
"""Test as dict."""
|
||||
config = ha.Config(None)
|
||||
config.config_dir = "/test/ha-config"
|
||||
config = ha.Config(None, "/test/ha-config")
|
||||
config.hass = MagicMock()
|
||||
type(config.hass.state).value = PropertyMock(return_value="RUNNING")
|
||||
expected = {
|
||||
|
@ -1501,7 +1498,7 @@ async def test_config_as_dict() -> None:
|
|||
|
||||
async def test_config_is_allowed_path() -> None:
|
||||
"""Test is_allowed_path method."""
|
||||
config = ha.Config(None)
|
||||
config = ha.Config(None, "/test/ha-config")
|
||||
with TemporaryDirectory() as tmp_dir:
|
||||
# The created dir is in /tmp. This is a symlink on OS X
|
||||
# causing this test to fail unless we resolve path first.
|
||||
|
@ -1533,7 +1530,7 @@ async def test_config_is_allowed_path() -> None:
|
|||
|
||||
async def test_config_is_allowed_external_url() -> None:
|
||||
"""Test is_allowed_external_url method."""
|
||||
config = ha.Config(None)
|
||||
config = ha.Config(None, "/test/ha-config")
|
||||
config.allowlist_external_urls = [
|
||||
"http://x.com/",
|
||||
"https://y.com/bla/",
|
||||
|
@ -1584,7 +1581,7 @@ async def test_start_taking_too_long(
|
|||
event_loop, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test when async_start takes too long."""
|
||||
hass = ha.HomeAssistant()
|
||||
hass = ha.HomeAssistant("/test/ha-config")
|
||||
caplog.set_level(logging.WARNING)
|
||||
hass.async_create_task(asyncio.sleep(0))
|
||||
|
||||
|
@ -1751,7 +1748,7 @@ async def test_additional_data_in_core_config(
|
|||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test that we can handle additional data in core configuration."""
|
||||
config = ha.Config(hass)
|
||||
config = ha.Config(hass, "/test/ha-config")
|
||||
hass_storage[ha.CORE_STORAGE_KEY] = {
|
||||
"version": 1,
|
||||
"data": {"location_name": "Test Name", "additional_valid_key": "value"},
|
||||
|
@ -1764,7 +1761,7 @@ async def test_incorrect_internal_external_url(
|
|||
hass: HomeAssistant, hass_storage: dict[str, Any], caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test that we warn when detecting invalid internal/external url."""
|
||||
config = ha.Config(hass)
|
||||
config = ha.Config(hass, "/test/ha-config")
|
||||
|
||||
hass_storage[ha.CORE_STORAGE_KEY] = {
|
||||
"version": 1,
|
||||
|
@ -1777,7 +1774,7 @@ async def test_incorrect_internal_external_url(
|
|||
assert "Invalid external_url set" not in caplog.text
|
||||
assert "Invalid internal_url set" not in caplog.text
|
||||
|
||||
config = ha.Config(hass)
|
||||
config = ha.Config(hass, "/test/ha-config")
|
||||
|
||||
hass_storage[ha.CORE_STORAGE_KEY] = {
|
||||
"version": 1,
|
||||
|
|
Loading…
Reference in New Issue