Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate weekday condition from time condition #32848

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
CONF_WAIT_TEMPLATE = "wait_template"
CONF_WEBHOOK_ID = "webhook_id"
CONF_WEEKDAY = "weekday"
CONF_DAYS = "days"
CONF_WHITE_VALUE = "white_value"
CONF_WHITELIST = "whitelist"
CONF_WHITELIST_EXTERNAL_DIRS = "whitelist_external_dirs"
Expand Down
31 changes: 31 additions & 0 deletions homeassistant/helpers/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
CONF_BEFORE,
CONF_BELOW,
CONF_CONDITION,
CONF_DAYS,
CONF_DEVICE_ID,
CONF_DOMAIN,
CONF_ENTITY_ID,
Expand Down Expand Up @@ -448,6 +449,36 @@ def time_if(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool:
return time_if


def weekdays(days: Union[None, str, Container[str]]) -> bool:
"""Test if weekday condition matches."""

if days is None:
return False

now = dt_util.now()
now_weekday = WEEKDAYS[now.weekday()]

if isinstance(days, str) and days != now_weekday or now_weekday not in days:
return False

return True


def weekday_from_config(
config: ConfigType, config_validation: bool = True
) -> ConditionCheckerType:
"""Wrap action method with weekday based condition."""
if config_validation:
config = cv.WEEKDAY_CONDITION_SCHEMA(config)
days = config.get(CONF_DAYS)

def weekday_if(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool:
"""Validate weekday based if-condition."""
return weekdays(days)

return weekday_if


def zone(
hass: HomeAssistant,
zone_ent: Union[None, str, State],
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/helpers/config_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ def make_entity_service_schema(
)

TIME_CONDITION_SCHEMA = vol.All(
deprecated("weekday", invalidation_version="0.109"),
vol.Schema(
{
vol.Required(CONF_CONDITION): "time",
Expand All @@ -891,6 +892,10 @@ def make_entity_service_schema(
has_at_least_one_key("before", "after", "weekday"),
)

WEEKDAY_CONDITION_SCHEMA = vol.Schema(
{vol.Required(CONF_CONDITION): "weekday", "days": weekdays}
)

ZONE_CONDITION_SCHEMA = vol.Schema(
{
vol.Required(CONF_CONDITION): "zone",
Expand Down Expand Up @@ -942,6 +947,7 @@ def make_entity_service_schema(
"sun": SUN_CONDITION_SCHEMA,
"template": TEMPLATE_CONDITION_SCHEMA,
"time": TIME_CONDITION_SCHEMA,
"weekday": WEEKDAY_CONDITION_SCHEMA,
"zone": ZONE_CONDITION_SCHEMA,
"and": AND_CONDITION_SCHEMA,
"or": OR_CONDITION_SCHEMA,
Expand Down
69 changes: 69 additions & 0 deletions tests/components/automation/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,37 @@ async def test_if_action_one_weekday(hass, calls):
assert 1 == len(calls)


async def test_if_action_one_weekday_new(hass, calls):
"""Test for if action with one weekday."""
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "event", "event_type": "test_event"},
"condition": {"condition": "weekday", "days": "mon"},
"action": {"service": "test.automation"},
}
},
)

days_past_monday = dt_util.now().weekday()
monday = dt_util.now() - timedelta(days=days_past_monday)
tuesday = monday + timedelta(days=1)

with patch("homeassistant.helpers.condition.dt_util.now", return_value=monday):
hass.bus.async_fire("test_event")
await hass.async_block_till_done()

assert 1 == len(calls)

with patch("homeassistant.helpers.condition.dt_util.now", return_value=tuesday):
hass.bus.async_fire("test_event")
await hass.async_block_till_done()

assert 1 == len(calls)


async def test_if_action_list_weekday(hass, calls):
"""Test for action with a list of weekdays."""
assert await async_setup_component(
Expand Down Expand Up @@ -207,3 +238,41 @@ async def test_if_action_list_weekday(hass, calls):
await hass.async_block_till_done()

assert 2 == len(calls)


async def test_if_action_list_weekday_new(hass, calls):
"""Test for action with a list of weekdays."""
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "event", "event_type": "test_event"},
"condition": {"condition": "weekday", "days": ["mon", "tue"]},
"action": {"service": "test.automation"},
}
},
)

days_past_monday = dt_util.now().weekday()
monday = dt_util.now() - timedelta(days=days_past_monday)
tuesday = monday + timedelta(days=1)
wednesday = tuesday + timedelta(days=1)

with patch("homeassistant.helpers.condition.dt_util.now", return_value=monday):
hass.bus.async_fire("test_event")
await hass.async_block_till_done()

assert 1 == len(calls)

with patch("homeassistant.helpers.condition.dt_util.now", return_value=tuesday):
hass.bus.async_fire("test_event")
await hass.async_block_till_done()

assert 2 == len(calls)

with patch("homeassistant.helpers.condition.dt_util.now", return_value=wednesday):
hass.bus.async_fire("test_event")
await hass.async_block_till_done()

assert 2 == len(calls)