Skip to content
Snippets Groups Projects
Unverified Commit d0c9a42b authored by Fabian Affolter's avatar Fabian Affolter Committed by GitHub
Browse files

Add custom validator for countries (#30280)

parent 33738cc8
No related branches found
No related tags found
No related merge requests found
......@@ -367,6 +367,7 @@ homeassistant/components/websocket_api/* @home-assistant/core
homeassistant/components/wemo/* @sqldiablo
homeassistant/components/withings/* @vangorra
homeassistant/components/wled/* @frenck
homeassistant/components/workday/* @fabaff
homeassistant/components/worldclock/* @fabaff
homeassistant/components/wwlln/* @bachya
homeassistant/components/xbox_live/* @MartinHjelmare
......
"""Sensor to indicate whether the current day is a workday."""
from datetime import datetime, timedelta
import logging
from typing import Any
import holidays
import voluptuous as vol
......@@ -11,111 +12,6 @@ import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
# List of all countries currently supported by holidays
# Source: https://github.com/dr-prodigy/python-holidays#available-countries
# There seems to be no way to get the list out at runtime
ALL_COUNTRIES = [
"Argentina",
"AR",
"Aruba",
"AW",
"Australia",
"AU",
"Austria",
"AT",
"Brazil",
"BR",
"Belarus",
"BY",
"Belgium",
"BE",
"Bulgaria",
"BG",
"Canada",
"CA",
"Colombia",
"CO",
"Croatia",
"HR",
"Czech",
"CZ",
"Denmark",
"DK",
"England",
"Estonia",
"EE",
"EuropeanCentralBank",
"ECB",
"TAR",
"Finland",
"FI",
"France",
"FRA",
"Germany",
"DE",
"Hungary",
"HU",
"Honduras",
"HND",
"Iceland",
"IS",
"India",
"IND",
"Ireland",
"IE",
"Isle of Man",
"Italy",
"IT",
"Japan",
"JP",
"Kenya",
"KE",
"Lithuania",
"LT",
"Luxembourg",
"LU",
"Mexico",
"MX",
"Netherlands",
"NL",
"NewZealand",
"NZ",
"Northern Ireland",
"Norway",
"NO",
"Peru",
"PE",
"Poland",
"Polish",
"PL",
"Portugal",
"PT",
"PortugalExt",
"PTE",
"Russia",
"RU",
"Scotland",
"Slovenia",
"SI",
"Slovakia",
"SK",
"South Africa",
"ZA",
"Spain",
"ES",
"Sweden",
"SE",
"Switzerland",
"CH",
"Ukraine",
"UA",
"UnitedKingdom",
"UK",
"UnitedStates",
"US",
"Wales",
]
ALLOWED_DAYS = WEEKDAYS + ["holiday"]
CONF_COUNTRY = "country"
......@@ -132,9 +28,28 @@ DEFAULT_EXCLUDES = ["sat", "sun", "holiday"]
DEFAULT_NAME = "Workday Sensor"
DEFAULT_OFFSET = 0
def valid_country(value: Any) -> str:
"""Validate that the given country is supported."""
value = cv.string(value)
all_supported_countries = holidays.list_supported_countries()
try:
raw_value = value.encode("utf-8")
except UnicodeError:
raise vol.Invalid(
"The country name or the abbreviation must be a valid UTF-8 string."
)
if not raw_value:
raise vol.Invalid("Country name or the abbreviation must not be empty.")
if value not in all_supported_countries:
raise vol.Invalid("Country is not supported.")
return value
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_COUNTRY): vol.In(ALL_COUNTRIES),
vol.Required(CONF_COUNTRY): valid_country,
vol.Optional(CONF_EXCLUDES, default=DEFAULT_EXCLUDES): vol.All(
cv.ensure_list, [vol.In(ALLOWED_DAYS)]
),
......@@ -151,13 +66,13 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Workday sensor."""
sensor_name = config.get(CONF_NAME)
country = config.get(CONF_COUNTRY)
province = config.get(CONF_PROVINCE)
workdays = config.get(CONF_WORKDAYS)
excludes = config.get(CONF_EXCLUDES)
days_offset = config.get(CONF_OFFSET)
add_holidays = config.get(CONF_ADD_HOLIDAYS)
country = config[CONF_COUNTRY]
days_offset = config[CONF_OFFSET]
excludes = config[CONF_EXCLUDES]
province = config.get(CONF_PROVINCE)
sensor_name = config[CONF_NAME]
workdays = config[CONF_WORKDAYS]
year = (get_date(datetime.today()) + timedelta(days=days_offset)).year
obj_holidays = getattr(holidays, country)(years=year)
......@@ -259,7 +174,7 @@ class IsWorkdaySensor(BinarySensorDevice):
# Default is no workday
self._state = False
# Get iso day of the week (1 = Monday, 7 = Sunday)
# Get ISO day of the week (1 = Monday, 7 = Sunday)
date = get_date(datetime.today()) + timedelta(days=self._days_offset)
day = date.isoweekday() - 1
day_of_week = day_to_string(day)
......
......@@ -3,8 +3,8 @@
"name": "Workday",
"documentation": "https://www.home-assistant.io/integrations/workday",
"requirements": [
"holidays==0.9.11"
"holidays==0.9.12"
],
"dependencies": [],
"codeowners": []
"codeowners": ["@fabaff"]
}
\ No newline at end of file
......@@ -663,7 +663,7 @@ hlk-sw16==0.0.7
hole==0.5.0
# homeassistant.components.workday
holidays==0.9.11
holidays==0.9.12
# homeassistant.components.frontend
home-assistant-frontend==20191204.1
......
......@@ -228,7 +228,7 @@ herepy==2.0.0
hole==0.5.0
# homeassistant.components.workday
holidays==0.9.11
holidays==0.9.12
# homeassistant.components.frontend
home-assistant-frontend==20191204.1
......
......@@ -2,7 +2,10 @@
from datetime import date
from unittest.mock import patch
from homeassistant.components.workday.binary_sensor import day_to_string
import pytest
import voluptuous as vol
import homeassistant.components.workday.binary_sensor as binary_sensor
from homeassistant.setup import setup_component
from tests.common import assert_setup_component, get_test_home_assistant
......@@ -68,6 +71,20 @@ class TestWorkdaySetup:
"""Stop everything that was started."""
self.hass.stop()
def test_valid_country(self):
"""Test topic name/filter validation."""
# Invalid UTF-8, must not contain U+D800 to U+DFFF
with pytest.raises(vol.Invalid):
binary_sensor.valid_country("\ud800")
with pytest.raises(vol.Invalid):
binary_sensor.valid_country("\udfff")
# Country MUST NOT be empty
with pytest.raises(vol.Invalid):
binary_sensor.valid_country("")
# Country must be supported by holidays
with pytest.raises(vol.Invalid):
binary_sensor.valid_country("HomeAssistantLand")
def test_setup_component_province(self):
"""Set up workday component."""
with assert_setup_component(1, "binary_sensor"):
......@@ -214,7 +231,7 @@ class TestWorkdaySetup:
def test_day_to_string(self):
"""Test if day_to_string is behaving correctly."""
assert day_to_string(0) == "mon"
assert day_to_string(1) == "tue"
assert day_to_string(7) == "holiday"
assert day_to_string(8) is None
assert binary_sensor.day_to_string(0) == "mon"
assert binary_sensor.day_to_string(1) == "tue"
assert binary_sensor.day_to_string(7) == "holiday"
assert binary_sensor.day_to_string(8) is None
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment