33import os
44import re
55import datetime
6- from typing import Any , Dict , List , Iterable , Optional
6+ from typing import Any , Dict , List , Union , Iterable , Optional
77
88import yaml
99import jsonschema
1010import pkg_resources
1111import jsonschema .exceptions
1212
13+ from routemaster .timezones import get_known_timezones
1314from routemaster .text_utils import join_comma_or
1415from routemaster .config .model import (
1516 Gate ,
2021 Webhook ,
2122 FeedConfig ,
2223 NextStates ,
23- TimeTrigger ,
2424 NoNextStates ,
2525 StateMachine ,
2626 DatabaseConfig ,
2929 MetadataTrigger ,
3030 ConstantNextState ,
3131 ContextNextStates ,
32+ SystemTimeTrigger ,
3233 LoggingPluginConfig ,
34+ TimezoneAwareTrigger ,
3335 ContextNextStatesOption ,
36+ MetadataTimezoneAwareTrigger ,
3437)
3538from routemaster .exit_conditions import ExitConditionProgram
3639from routemaster .config .exceptions import ConfigError
@@ -249,11 +252,6 @@ def _load_gate(path: Path, yaml_state: Yaml, feed_names: List[str]) -> Gate:
249252
250253
251254def _load_trigger (path : Path , yaml_trigger : Yaml ) -> Trigger :
252- if len (yaml_trigger .keys ()) > 1 : # pragma: no branch
253- raise ConfigError ( # pragma: no cover
254- f"Trigger at path { '.' .join (path )} cannot be of multiple types." ,
255- )
256-
257255 if 'time' in yaml_trigger :
258256 return _load_time_trigger (path , yaml_trigger )
259257 elif 'metadata' in yaml_trigger :
@@ -269,7 +267,22 @@ def _load_trigger(path: Path, yaml_trigger: Yaml) -> Trigger:
269267 )
270268
271269
272- def _load_time_trigger (path : Path , yaml_trigger : Yaml ) -> TimeTrigger :
270+ def _validate_known_timezone (path : Path , timezone : str ) -> None :
271+ if timezone not in get_known_timezones ():
272+ raise ConfigError (
273+ f"Timezone '{ timezone } ' at path { '.' .join (path )} is not a known "
274+ f"timezone." ,
275+ )
276+
277+
278+ def _load_time_trigger (
279+ path : Path ,
280+ yaml_trigger : Yaml ,
281+ ) -> Union [
282+ SystemTimeTrigger ,
283+ TimezoneAwareTrigger ,
284+ MetadataTimezoneAwareTrigger ,
285+ ]:
273286 format_ = '%Hh%Mm'
274287 try :
275288 dt = datetime .datetime .strptime (str (yaml_trigger ['time' ]), format_ )
@@ -279,7 +292,21 @@ def _load_time_trigger(path: Path, yaml_trigger: Yaml) -> TimeTrigger:
279292 f"Time trigger '{ yaml_trigger ['time' ]} ' at path { '.' .join (path )} "
280293 f"does not meet expected format: { format_ } ." ,
281294 ) from None
282- return TimeTrigger (time = trigger )
295+
296+ if 'timezone' in yaml_trigger :
297+ timezone_path = path + ['timezone' ]
298+ timezone : str = yaml_trigger ['timezone' ]
299+ if timezone .startswith ('metadata.' ):
300+ _validate_context_lookups (timezone_path , [timezone ], [])
301+ return MetadataTimezoneAwareTrigger (
302+ time = trigger ,
303+ timezone_metadata_path = timezone .split ('.' )[1 :],
304+ )
305+ else :
306+ _validate_known_timezone (timezone_path , timezone )
307+ return TimezoneAwareTrigger (time = trigger , timezone = timezone )
308+
309+ return SystemTimeTrigger (time = trigger )
283310
284311
285312RE_INTERVAL = re .compile (
0 commit comments