Add custom validator for countries (#30280)

This commit is contained in:
Fabian Affolter 2019-12-30 17:51:25 +01:00 committed by GitHub
parent 33738cc83a
commit d0c9a42b81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 122 deletions

View File

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

View File

@ -1,6 +1,7 @@
"""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)

View File

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

View 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

View File

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

View File

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