2019-05-13 08:16:55 +00:00
|
|
|
"""Generate config flow file."""
|
2021-03-18 21:58:19 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2019-05-13 08:16:55 +00:00
|
|
|
import json
|
|
|
|
|
2019-12-09 15:24:03 +00:00
|
|
|
from .model import Config, Integration
|
2019-05-13 08:16:55 +00:00
|
|
|
|
|
|
|
BASE = """
|
|
|
|
\"\"\"Automatically generated by hassfest.
|
|
|
|
|
2019-05-30 16:41:30 +00:00
|
|
|
To update, run python3 -m script.hassfest
|
2019-05-13 08:16:55 +00:00
|
|
|
\"\"\"
|
|
|
|
|
2019-09-09 19:01:49 +00:00
|
|
|
# fmt: off
|
2019-05-13 08:16:55 +00:00
|
|
|
|
|
|
|
FLOWS = {}
|
|
|
|
""".strip()
|
|
|
|
|
2020-06-12 15:38:38 +00:00
|
|
|
UNIQUE_ID_IGNORE = {"huawei_lte", "mqtt", "adguard"}
|
2020-04-27 17:36:56 +00:00
|
|
|
|
2019-05-13 08:16:55 +00:00
|
|
|
|
2020-04-27 17:36:56 +00:00
|
|
|
def validate_integration(config: Config, integration: Integration):
|
|
|
|
"""Validate config flow of an integration."""
|
|
|
|
config_flow_file = integration.path / "config_flow.py"
|
|
|
|
|
|
|
|
if not config_flow_file.is_file():
|
2020-07-06 09:21:40 +00:00
|
|
|
if integration.manifest.get("config_flow"):
|
2020-06-15 11:38:38 +00:00
|
|
|
integration.add_error(
|
|
|
|
"config_flow",
|
|
|
|
"Config flows need to be defined in the file config_flow.py",
|
|
|
|
)
|
2020-04-27 17:36:56 +00:00
|
|
|
return
|
|
|
|
|
2020-06-12 15:38:38 +00:00
|
|
|
config_flow = config_flow_file.read_text()
|
|
|
|
|
|
|
|
needs_unique_id = integration.domain not in UNIQUE_ID_IGNORE and (
|
2020-06-15 11:38:38 +00:00
|
|
|
"async_step_discovery" in config_flow
|
|
|
|
or "async_step_hassio" in config_flow
|
|
|
|
or "async_step_homekit" in config_flow
|
2020-10-07 16:30:51 +00:00
|
|
|
or "async_step_mqtt" in config_flow
|
2020-06-15 11:38:38 +00:00
|
|
|
or "async_step_ssdp" in config_flow
|
|
|
|
or "async_step_zeroconf" in config_flow
|
2021-01-14 08:09:08 +00:00
|
|
|
or "async_step_dhcp" in config_flow
|
2021-08-20 19:04:18 +00:00
|
|
|
or "async_step_usb" in config_flow
|
2020-04-27 17:36:56 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if not needs_unique_id:
|
|
|
|
return
|
|
|
|
|
|
|
|
has_unique_id = (
|
|
|
|
"self.async_set_unique_id" in config_flow
|
2020-06-15 11:38:38 +00:00
|
|
|
or "self._async_handle_discovery_without_unique_id" in config_flow
|
|
|
|
or "register_discovery_flow" in config_flow
|
|
|
|
or "AbstractOAuth2FlowHandler" in config_flow
|
2020-04-27 17:36:56 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if has_unique_id:
|
|
|
|
return
|
|
|
|
|
|
|
|
if config.specific_integrations:
|
|
|
|
notice_method = integration.add_warning
|
|
|
|
else:
|
|
|
|
notice_method = integration.add_error
|
|
|
|
|
|
|
|
notice_method(
|
|
|
|
"config_flow", "Config flows that are discoverable need to set a unique ID"
|
|
|
|
)
|
|
|
|
|
2019-05-13 08:16:55 +00:00
|
|
|
|
2021-03-18 21:58:19 +00:00
|
|
|
def generate_and_validate(integrations: dict[str, Integration], config: Config):
|
2019-05-13 08:16:55 +00:00
|
|
|
"""Validate and generate config flow data."""
|
2022-03-21 03:38:13 +00:00
|
|
|
domains = {
|
|
|
|
"integration": [],
|
|
|
|
"helper": [],
|
|
|
|
}
|
2019-05-13 08:16:55 +00:00
|
|
|
|
|
|
|
for domain in sorted(integrations):
|
|
|
|
integration = integrations[domain]
|
|
|
|
|
2021-08-16 14:28:26 +00:00
|
|
|
if not integration.manifest or not integration.config_flow:
|
2019-05-13 08:16:55 +00:00
|
|
|
continue
|
|
|
|
|
2020-04-27 17:36:56 +00:00
|
|
|
validate_integration(config, integration)
|
2019-05-13 08:16:55 +00:00
|
|
|
|
2022-03-21 03:38:13 +00:00
|
|
|
domains[integration.integration_type].append(domain)
|
2019-05-13 08:16:55 +00:00
|
|
|
|
|
|
|
return BASE.format(json.dumps(domains, indent=4))
|
|
|
|
|
|
|
|
|
2021-03-18 21:58:19 +00:00
|
|
|
def validate(integrations: dict[str, Integration], config: Config):
|
2019-05-13 08:16:55 +00:00
|
|
|
"""Validate config flow file."""
|
2019-07-31 19:25:30 +00:00
|
|
|
config_flow_path = config.root / "homeassistant/generated/config_flows.py"
|
2020-04-27 17:36:56 +00:00
|
|
|
config.cache["config_flow"] = content = generate_and_validate(integrations, config)
|
2019-05-13 08:16:55 +00:00
|
|
|
|
2020-04-16 16:00:04 +00:00
|
|
|
if config.specific_integrations:
|
|
|
|
return
|
|
|
|
|
2020-04-05 10:49:57 +00:00
|
|
|
with open(str(config_flow_path)) as fp:
|
2019-05-13 08:16:55 +00:00
|
|
|
if fp.read().strip() != content:
|
|
|
|
config.add_error(
|
|
|
|
"config_flow",
|
|
|
|
"File config_flows.py is not up to date. "
|
|
|
|
"Run python3 -m script.hassfest",
|
2019-07-31 19:25:30 +00:00
|
|
|
fixable=True,
|
2019-05-13 08:16:55 +00:00
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
|
2021-03-18 21:58:19 +00:00
|
|
|
def generate(integrations: dict[str, Integration], config: Config):
|
2019-05-13 08:16:55 +00:00
|
|
|
"""Generate config flow file."""
|
2019-07-31 19:25:30 +00:00
|
|
|
config_flow_path = config.root / "homeassistant/generated/config_flows.py"
|
|
|
|
with open(str(config_flow_path), "w") as fp:
|
2020-04-04 18:17:11 +00:00
|
|
|
fp.write(f"{config.cache['config_flow']}\n")
|