Skip to content

Commit

Permalink
Merge branch 'dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
sepahewe authored Oct 9, 2024
2 parents 91e02e4 + fa53ec4 commit f1939d9
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 126 deletions.
20 changes: 8 additions & 12 deletions homeassistant/components/brother/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from homeassistant.components import zeroconf
from homeassistant.components.snmp import async_get_snmp_engine
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
Expand Down Expand Up @@ -49,8 +49,6 @@ class BrotherConfigFlow(ConfigFlow, domain=DOMAIN):

VERSION = 1

entry: ConfigEntry

def __init__(self) -> None:
"""Initialize."""
self.brother: Brother
Expand Down Expand Up @@ -145,18 +143,18 @@ async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a reconfiguration flow initialized by the user."""
self.entry = self._get_reconfigure_entry()
return await self.async_step_reconfigure_confirm()

async def async_step_reconfigure_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a reconfiguration flow initialized by the user."""
entry = self._get_reconfigure_entry()
errors = {}

if user_input is not None:
try:
await validate_input(self.hass, user_input, self.entry.unique_id)
await validate_input(self.hass, user_input, entry.unique_id)
except InvalidHost:
errors[CONF_HOST] = "wrong_host"
except (ConnectionError, TimeoutError):
Expand All @@ -166,20 +164,18 @@ async def async_step_reconfigure_confirm(
except AnotherDevice:
errors["base"] = "another_device"
else:
self.hass.config_entries.async_update_entry(
self.entry,
data=self.entry.data | {CONF_HOST: user_input[CONF_HOST]},
return self.async_update_reload_and_abort(
entry,
data_updates={CONF_HOST: user_input[CONF_HOST]},
)
await self.hass.config_entries.async_reload(self.entry.entry_id)
return self.async_abort(reason="reconfigure_successful")

return self.async_show_form(
step_id="reconfigure_confirm",
data_schema=self.add_suggested_values_to_schema(
data_schema=RECONFIGURE_SCHEMA,
suggested_values=self.entry.data | (user_input or {}),
suggested_values=entry.data | (user_input or {}),
),
description_placeholders={"printer_name": self.entry.title},
description_placeholders={"printer_name": entry.title},
errors=errors,
)

Expand Down
58 changes: 2 additions & 56 deletions homeassistant/components/habitica/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
from habitipy.aio import HabitipyAsync
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_NAME,
CONF_API_KEY,
CONF_NAME,
CONF_SENSORS,
CONF_URL,
CONF_VERIFY_SSL,
Platform,
Expand Down Expand Up @@ -43,7 +41,6 @@
ATTR_SKILL,
ATTR_TASK,
CONF_API_USER,
DEFAULT_URL,
DOMAIN,
EVENT_API_CALL_SUCCESS,
SERVICE_API_CALL,
Expand All @@ -52,54 +49,14 @@
from .coordinator import HabiticaDataUpdateCoordinator

_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)

type HabiticaConfigEntry = ConfigEntry[HabiticaDataUpdateCoordinator]

SENSORS_TYPES = ["name", "hp", "maxHealth", "mp", "maxMP", "exp", "toNextLevel", "lvl"]

INSTANCE_SCHEMA = vol.All(
cv.deprecated(CONF_SENSORS),
vol.Schema(
{
vol.Optional(CONF_URL, default=DEFAULT_URL): cv.url,
vol.Optional(CONF_NAME): cv.string,
vol.Required(CONF_API_USER): cv.string,
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_SENSORS, default=list(SENSORS_TYPES)): vol.All(
cv.ensure_list, vol.Unique(), [vol.In(list(SENSORS_TYPES))]
),
}
),
)

has_unique_values = vol.Schema(vol.Unique())
# because we want a handy alias


def has_all_unique_users(value):
"""Validate that all API users are unique."""
api_users = [user[CONF_API_USER] for user in value]
has_unique_values(api_users)
return value


def has_all_unique_users_names(value):
"""Validate that all user's names are unique and set if any is set."""
names = [user.get(CONF_NAME) for user in value]
if None in names and any(name is not None for name in names):
raise vol.Invalid("user names of all users must be set if any is set")
if not all(name is None for name in names):
has_unique_values(names)
return value


INSTANCE_LIST_SCHEMA = vol.All(
cv.ensure_list, has_all_unique_users, has_all_unique_users_names, [INSTANCE_SCHEMA]
)
CONFIG_SCHEMA = vol.Schema({DOMAIN: INSTANCE_LIST_SCHEMA}, extra=vol.ALLOW_EXTRA)

PLATFORMS = [Platform.BUTTON, Platform.SENSOR, Platform.SWITCH, Platform.TODO]


SERVICE_API_CALL_SCHEMA = vol.Schema(
{
vol.Required(ATTR_NAME): str,
Expand All @@ -118,17 +75,6 @@ def has_all_unique_users_names(value):

async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Habitica service."""
configs = config.get(DOMAIN, [])

for conf in configs:
if conf.get(CONF_URL) is None:
conf[CONF_URL] = DEFAULT_URL

hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf
)
)

async def cast_skill(call: ServiceCall) -> ServiceResponse:
"""Skill action."""
Expand Down
20 changes: 0 additions & 20 deletions homeassistant/components/habitica/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
CONF_USERNAME,
CONF_VERIFY_SSL,
)
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.selector import (
TextSelector,
TextSelectorConfig,
Expand Down Expand Up @@ -178,21 +176,3 @@ async def async_step_advanced(
),
errors=errors,
)

async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import habitica config from configuration.yaml."""

async_create_issue(
self.hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_yaml_{DOMAIN}",
is_fixable=False,
breaks_in_ha_version="2024.11.0",
severity=IssueSeverity.WARNING,
translation_key="deprecated_yaml",
translation_placeholders={
"domain": DOMAIN,
"integration_title": "Habitica",
},
)
return await self.async_step_advanced(import_data)
37 changes: 0 additions & 37 deletions tests/components/habitica/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType

from tests.common import MockConfigEntry

MOCK_DATA_LOGIN_STEP = {
CONF_USERNAME: "[email protected]",
CONF_PASSWORD: "test-password",
Expand Down Expand Up @@ -217,38 +215,3 @@ async def test_form_advanced_errors(

assert result2["type"] is FlowResultType.FORM
assert result2["errors"] == {"base": text_error}


async def test_manual_flow_config_exist(hass: HomeAssistant) -> None:
"""Test config flow discovers only already configured config."""
MockConfigEntry(
domain=DOMAIN,
unique_id="test-api-user",
data={"api_user": "test-api-user", "api_key": "test-api-key"},
).add_to_hass(hass)

result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}
)

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "advanced"

mock_obj = MagicMock()
mock_obj.user.get = AsyncMock(return_value={"api_user": "test-api-user"})

with patch(
"homeassistant.components.habitica.config_flow.HabitipyAsync",
return_value=mock_obj,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"url": DEFAULT_URL,
"api_user": "test-api-user",
"api_key": "test-api-key",
},
)

assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
34 changes: 34 additions & 0 deletions tests/components/workday/snapshots/test_binary_sensor.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,55 @@
'workday',
'bad_date_holiday-1-2024_08_15',
): IssueRegistryItemSnapshot({
'active': True,
'breaks_in_ha_version': None,
'created': <ANY>,
'data': dict({
'country': 'DE',
'entry_id': '1',
'named_holiday': '2024-08-15',
}),
'dismissed_version': None,
'domain': 'workday',
'is_fixable': True,
'is_persistent': False,
'issue_domain': None,
'issue_id': 'bad_date_holiday-1-2024_08_15',
'learn_more_url': None,
'severity': <IssueSeverity.WARNING: 'warning'>,
'translation_key': 'bad_date_holiday',
'translation_placeholders': dict({
'country': 'DE',
'remove_holidays': '2024-08-15',
'title': 'Mock Title',
}),
}),
tuple(
'workday',
'bad_date_holiday-1-2025_08_15',
): IssueRegistryItemSnapshot({
'active': True,
'breaks_in_ha_version': None,
'created': <ANY>,
'data': dict({
'country': 'DE',
'entry_id': '1',
'named_holiday': '2025-08-15',
}),
'dismissed_version': None,
'domain': 'workday',
'is_fixable': True,
'is_persistent': False,
'issue_domain': None,
'issue_id': 'bad_date_holiday-1-2025_08_15',
'learn_more_url': None,
'severity': <IssueSeverity.WARNING: 'warning'>,
'translation_key': 'bad_date_holiday',
'translation_placeholders': dict({
'country': 'DE',
'remove_holidays': '2025-08-15',
'title': 'Mock Title',
}),
}),
})
# ---
2 changes: 1 addition & 1 deletion tests/syrupy.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def _serializable_issue_registry_entry(
cls, data: ir.IssueEntry
) -> SerializableData:
"""Prepare a Home Assistant issue registry entry for serialization."""
return IssueRegistryItemSnapshot(data.to_json() | {"created": ANY})
return IssueRegistryItemSnapshot(dataclasses.asdict(data) | {"created": ANY})

@classmethod
def _serializable_state(cls, data: State) -> SerializableData:
Expand Down

0 comments on commit f1939d9

Please sign in to comment.