Skip to content

Commit 8729f85

Browse files
committed
refactor: use getattr for time range
1 parent c42d477 commit 8729f85

File tree

3 files changed

+34
-25
lines changed

3 files changed

+34
-25
lines changed

aws_lambda_powertools/utilities/feature_flags/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Advanced feature flags utility"""
2+
23
from .appconfig import AppConfigStore
34
from .base import StoreProvider
45
from .exceptions import ConfigurationStoreError

aws_lambda_powertools/utilities/feature_flags/schema.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -362,15 +362,7 @@ def validate_condition_value(condition: Dict[str, Any], rule_name: str):
362362

363363
validator(value, rule_name)
364364

365-
# time actions need to be parsed to make sure date and time format is valid and timezone is recognized
366-
if action == RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value:
367-
ConditionsValidator._validate_schedule_between_time_and_datetime_ranges(
368-
value,
369-
rule_name,
370-
action,
371-
ConditionsValidator._validate_time_value,
372-
)
373-
elif action == RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value:
365+
if action == RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value:
374366
ConditionsValidator._validate_schedule_between_time_and_datetime_ranges(
375367
value,
376368
rule_name,
@@ -408,16 +400,6 @@ def _validate_datetime_value(datetime_str: str, rule_name: str):
408400
f"field, rule={rule_name} ",
409401
)
410402

411-
@staticmethod
412-
def _validate_time_value(time: str, rule_name: str):
413-
# Using a regex instead of strptime because it's several orders of magnitude faster
414-
match = TIME_RANGE_RE_PATTERN.match(time)
415-
416-
if not match:
417-
raise SchemaValidationError(
418-
f"'START' and 'END' must be a valid time format, time_format={TIME_RANGE_FORMAT}, rule={rule_name}",
419-
)
420-
421403
@staticmethod
422404
def _validate_schedule_between_days_of_week_value(value: dict, rule_name: str):
423405
error_str = f"condition with a CURRENT_DAY_OF_WEEK action must have a condition value dictionary with 'DAYS' and 'TIMEZONE' (optional) keys, rule={rule_name}" # noqa: E501
@@ -449,6 +431,35 @@ def _validate_schedule_between_days_of_week_value(value: dict, rule_name: str):
449431
if not tz.gettz(timezone):
450432
raise SchemaValidationError(f"'TIMEZONE' value must represent a valid IANA timezone, rule={rule_name}")
451433

434+
@staticmethod
435+
def _validate_schedule_between_time_range_value(value: Dict, rule_name: str) -> bool:
436+
if not isinstance(value, dict):
437+
raise SchemaValidationError(
438+
f"{RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value} action must have a dictionary with 'START' and 'END' keys, rule={rule_name}", # noqa: E501
439+
)
440+
441+
start_time = value.get(TimeValues.START.value, "")
442+
end_time = value.get(TimeValues.END.value, "")
443+
444+
if not isinstance(start_time, str) or not isinstance(end_time, str):
445+
raise SchemaValidationError(f"'START' and 'END' must be a non empty string, rule={rule_name}")
446+
447+
# Using a regex instead of strptime because it's several orders of magnitude faster
448+
if not TIME_RANGE_RE_PATTERN.match(start_time) or not TIME_RANGE_RE_PATTERN.match(end_time):
449+
raise SchemaValidationError(
450+
f"'START' and 'END' must be a valid time format, time_format={TIME_RANGE_FORMAT}, rule={rule_name}",
451+
)
452+
453+
timezone = value.get(TimeValues.TIMEZONE.value, "UTC")
454+
if not isinstance(timezone, str):
455+
raise SchemaValidationError(f"'TIMEZONE' must be a string, rule={rule_name}")
456+
457+
# try to see if the timezone string corresponds to any known timezone
458+
if not tz.gettz(timezone):
459+
raise SchemaValidationError(f"'TIMEZONE' value must represent a valid IANA timezone, rule={rule_name}")
460+
461+
return True
462+
452463
@staticmethod
453464
def _validate_schedule_between_time_and_datetime_ranges(
454465
value: Any,

tests/functional/feature_flags/test_schema_validation.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def test_validate_time_condition_between_time_range_invalid_condition_value():
441441
# THEN raise SchemaValidationError
442442
with pytest.raises(
443443
SchemaValidationError,
444-
match=f"condition with a 'SCHEDULE_BETWEEN_TIME_RANGE' action must have a condition value type dictionary with 'START' and 'END' keys, rule={rule_name}", # noqa: E501
444+
match=f"SCHEDULE_BETWEEN_TIME_RANGE action must have a dictionary with 'START' and 'END' keys, rule={rule_name}", # noqa: E501
445445
):
446446
ConditionsValidator.validate_condition_value(condition=condition, rule_name=rule_name)
447447

@@ -460,7 +460,7 @@ def test_validate_time_condition_between_time_range_invalid_condition_value_no_s
460460
# THEN raise SchemaValidationError
461461
with pytest.raises(
462462
SchemaValidationError,
463-
match=f"condition with a 'SCHEDULE_BETWEEN_TIME_RANGE' action must have a condition value type dictionary with 'START' and 'END' keys, rule={rule_name}", # noqa: E501
463+
match="'START' and 'END' must be a valid time format",
464464
):
465465
ConditionsValidator.validate_condition_value(condition=condition, rule_name=rule_name)
466466

@@ -477,10 +477,7 @@ def test_validate_time_condition_between_time_range_invalid_condition_value_no_e
477477

478478
# WHEN calling validate_condition
479479
# THEN raise SchemaValidationError
480-
with pytest.raises(
481-
SchemaValidationError,
482-
match=f"condition with a 'SCHEDULE_BETWEEN_TIME_RANGE' action must have a condition value type dictionary with 'START' and 'END' keys, rule={rule_name}", # noqa: E501
483-
):
480+
with pytest.raises(SchemaValidationError, match="'START' and 'END' must be a valid time format"):
484481
ConditionsValidator.validate_condition_value(condition=condition, rule_name=rule_name)
485482

486483

0 commit comments

Comments
 (0)