mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 10:17:51 +00:00
Update country province
validation (#84463)
* Update country `province` validation. * Run pre-commit. * Add tests * Mod config flow --------- Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
parent
f96446cb24
commit
7827f9ccae
@ -4,8 +4,13 @@ from __future__ import annotations
|
|||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import holidays
|
from holidays import (
|
||||||
from holidays import DateLike, HolidayBase
|
DateLike,
|
||||||
|
HolidayBase,
|
||||||
|
__version__ as python_holidays_version,
|
||||||
|
country_holidays,
|
||||||
|
list_supported_countries,
|
||||||
|
)
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
@ -43,7 +48,6 @@ from .const import (
|
|||||||
def valid_country(value: Any) -> str:
|
def valid_country(value: Any) -> str:
|
||||||
"""Validate that the given country is supported."""
|
"""Validate that the given country is supported."""
|
||||||
value = cv.string(value)
|
value = cv.string(value)
|
||||||
all_supported_countries = holidays.list_supported_countries()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
raw_value = value.encode("utf-8")
|
raw_value = value.encode("utf-8")
|
||||||
@ -53,7 +57,7 @@ def valid_country(value: Any) -> str:
|
|||||||
) from err
|
) from err
|
||||||
if not raw_value:
|
if not raw_value:
|
||||||
raise vol.Invalid("Country name or the abbreviation must not be empty.")
|
raise vol.Invalid("Country name or the abbreviation must not be empty.")
|
||||||
if value not in all_supported_countries:
|
if value not in list_supported_countries():
|
||||||
raise vol.Invalid("Country is not supported.")
|
raise vol.Invalid("Country is not supported.")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@ -123,17 +127,17 @@ async def async_setup_entry(
|
|||||||
province: str | None = entry.options.get(CONF_PROVINCE)
|
province: str | None = entry.options.get(CONF_PROVINCE)
|
||||||
sensor_name: str = entry.options[CONF_NAME]
|
sensor_name: str = entry.options[CONF_NAME]
|
||||||
workdays: list[str] = entry.options[CONF_WORKDAYS]
|
workdays: list[str] = entry.options[CONF_WORKDAYS]
|
||||||
|
|
||||||
cls: HolidayBase = getattr(holidays, country)
|
|
||||||
year: int = (dt_util.now() + timedelta(days=days_offset)).year
|
year: int = (dt_util.now() + timedelta(days=days_offset)).year
|
||||||
|
|
||||||
if province and province not in cls.subdivisions:
|
if country and country not in list_supported_countries():
|
||||||
|
LOGGER.error("There is no country %s", country)
|
||||||
|
return
|
||||||
|
|
||||||
|
if province and province not in list_supported_countries()[country]:
|
||||||
LOGGER.error("There is no subdivision %s in country %s", province, country)
|
LOGGER.error("There is no subdivision %s in country %s", province, country)
|
||||||
return
|
return
|
||||||
|
|
||||||
obj_holidays = cls(
|
obj_holidays: HolidayBase = country_holidays(country, subdiv=province, years=year)
|
||||||
subdiv=province, years=year, language=cls.default_language
|
|
||||||
) # type: ignore[operator]
|
|
||||||
|
|
||||||
# Add custom holidays
|
# Add custom holidays
|
||||||
try:
|
try:
|
||||||
@ -209,7 +213,7 @@ class IsWorkdaySensor(BinarySensorEntity):
|
|||||||
entry_type=DeviceEntryType.SERVICE,
|
entry_type=DeviceEntryType.SERVICE,
|
||||||
identifiers={(DOMAIN, entry_id)},
|
identifiers={(DOMAIN, entry_id)},
|
||||||
manufacturer="python-holidays",
|
manufacturer="python-holidays",
|
||||||
model=holidays.__version__,
|
model=python_holidays_version,
|
||||||
name=name,
|
name=name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import holidays
|
from holidays import HolidayBase, country_holidays, list_supported_countries
|
||||||
from holidays import HolidayBase, list_supported_countries
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import (
|
from homeassistant.config_entries import (
|
||||||
@ -77,12 +76,14 @@ def validate_custom_dates(user_input: dict[str, Any]) -> None:
|
|||||||
if dt_util.parse_date(add_date) is None:
|
if dt_util.parse_date(add_date) is None:
|
||||||
raise AddDatesError("Incorrect date")
|
raise AddDatesError("Incorrect date")
|
||||||
|
|
||||||
cls: HolidayBase = getattr(holidays, user_input[CONF_COUNTRY])
|
cls: HolidayBase = country_holidays(user_input[CONF_COUNTRY])
|
||||||
year: int = dt_util.now().year
|
year: int = dt_util.now().year
|
||||||
|
obj_holidays: HolidayBase = country_holidays(
|
||||||
obj_holidays = cls(
|
user_input[CONF_COUNTRY],
|
||||||
subdiv=user_input.get(CONF_PROVINCE), years=year, language=cls.default_language
|
subdiv=user_input.get(CONF_PROVINCE),
|
||||||
) # type: ignore[operator]
|
years=year,
|
||||||
|
language=cls.default_language,
|
||||||
|
)
|
||||||
|
|
||||||
for remove_date in user_input[CONF_REMOVE_HOLIDAYS]:
|
for remove_date in user_input[CONF_REMOVE_HOLIDAYS]:
|
||||||
if dt_util.parse_date(remove_date) is None:
|
if dt_util.parse_date(remove_date) is None:
|
||||||
|
@ -50,6 +50,15 @@ TEST_CONFIG_WITH_PROVINCE = {
|
|||||||
"add_holidays": [],
|
"add_holidays": [],
|
||||||
"remove_holidays": [],
|
"remove_holidays": [],
|
||||||
}
|
}
|
||||||
|
TEST_CONFIG_INCORRECT_COUNTRY = {
|
||||||
|
"name": DEFAULT_NAME,
|
||||||
|
"country": "ZZ",
|
||||||
|
"excludes": DEFAULT_EXCLUDES,
|
||||||
|
"days_offset": DEFAULT_OFFSET,
|
||||||
|
"workdays": DEFAULT_WORKDAYS,
|
||||||
|
"add_holidays": [],
|
||||||
|
"remove_holidays": [],
|
||||||
|
}
|
||||||
TEST_CONFIG_INCORRECT_PROVINCE = {
|
TEST_CONFIG_INCORRECT_PROVINCE = {
|
||||||
"name": DEFAULT_NAME,
|
"name": DEFAULT_NAME,
|
||||||
"country": "DE",
|
"country": "DE",
|
||||||
|
@ -17,6 +17,7 @@ from . import (
|
|||||||
TEST_CONFIG_EXAMPLE_2,
|
TEST_CONFIG_EXAMPLE_2,
|
||||||
TEST_CONFIG_INCLUDE_HOLIDAY,
|
TEST_CONFIG_INCLUDE_HOLIDAY,
|
||||||
TEST_CONFIG_INCORRECT_ADD_REMOVE,
|
TEST_CONFIG_INCORRECT_ADD_REMOVE,
|
||||||
|
TEST_CONFIG_INCORRECT_COUNTRY,
|
||||||
TEST_CONFIG_INCORRECT_PROVINCE,
|
TEST_CONFIG_INCORRECT_PROVINCE,
|
||||||
TEST_CONFIG_NO_PROVINCE,
|
TEST_CONFIG_NO_PROVINCE,
|
||||||
TEST_CONFIG_NO_STATE,
|
TEST_CONFIG_NO_STATE,
|
||||||
@ -187,6 +188,21 @@ async def test_setup_day_after_tomorrow(
|
|||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup_faulty_country(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test setup with faulty province."""
|
||||||
|
freezer.move_to(datetime(2017, 1, 6, 12, tzinfo=UTC)) # Friday
|
||||||
|
await init_integration(hass, TEST_CONFIG_INCORRECT_COUNTRY)
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.workday_sensor")
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
assert "There is no country" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_faulty_province(
|
async def test_setup_faulty_province(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user