Don't allow hass.config.config_dir to be None (#98442)

pull/98534/head
Erik Montnemery 2023-08-16 13:00:14 +02:00 committed by GitHub
parent 5ed3e90607
commit 91faa53843
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 28 additions and 56 deletions

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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]

View File

@ -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)]))
)

View File

@ -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"]

View File

@ -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)])

View File

@ -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(

View File

@ -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:

View File

@ -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,

View File

@ -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]:

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,