Skip to content

Commit e1d4a3a

Browse files
committed
Code review items
1 parent 6ca4ca4 commit e1d4a3a

File tree

4 files changed

+34
-37
lines changed

4 files changed

+34
-37
lines changed

featuremanagement/_defaultfilters.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ def evaluate(self, context: Mapping[Any, Any], **kwargs: Any) -> bool:
7171

7272
current_time = datetime.now(timezone.utc)
7373

74-
if recurrence_data:
75-
recurrence = Recurrence(recurrence_data)
76-
7774
if not start and not end:
7875
logger.warning(
7976
TIME_WINDOW_FILTER_INVALID,
@@ -87,24 +84,19 @@ def evaluate(self, context: Mapping[Any, Any], **kwargs: Any) -> bool:
8784
start_time: Optional[datetime] = parsedate_to_datetime(start) if start else None
8885
end_time: Optional[datetime] = parsedate_to_datetime(end) if end else None
8986

90-
if recurrence:
91-
if start_time and end_time:
92-
settings = TimeWindowFilterSettings(start_time, end_time, recurrence)
93-
return is_match(settings, current_time)
94-
logger.warning(
95-
TIME_WINDOW_FILTER_INVALID_RECURRENCE,
96-
TimeWindowFilter.__name__,
97-
context.get(FEATURE_FLAG_NAME_KEY),
98-
START_KEY,
99-
END_KEY,
100-
)
101-
return False
102-
10387
if not start and not end:
10488
logging.warning("%s: At least one of Start or End is required.", TimeWindowFilter.__name__)
10589
return False
10690

107-
return (start_time is None or start_time <= current_time) and (end_time is None or current_time < end_time)
91+
if (start_time is None or start_time <= current_time) and (end_time is None or current_time < end_time):
92+
return True
93+
94+
if recurrence_data:
95+
recurrence = Recurrence(recurrence_data)
96+
settings = TimeWindowFilterSettings(start_time, end_time, recurrence)
97+
return is_match(settings, current_time)
98+
99+
return False
108100

109101

110102
@FeatureFilter.alias("Microsoft.Targeting")

featuremanagement/_time_window_filter/_models.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under the MIT License. See License.txt in the project root for
44
# license information.
55
# -------------------------------------------------------------------------
6+
import math
67
from enum import Enum
78
from typing import Dict, Any, Optional
89
from datetime import datetime
@@ -68,7 +69,8 @@ class RecurrencePattern: # pylint: disable=too-few-public-methods
6869
The recurrence pattern settings.
6970
"""
7071

71-
days: list = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
72+
days: list = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
73+
days_of_week: list = []
7274

7375
def __init__(self, pattern_data: Dict[str, Any]):
7476
self.type = RecurrencePatternType.from_str(pattern_data.get("Type", "Daily"))
@@ -78,21 +80,23 @@ def __init__(self, pattern_data: Dict[str, Any]):
7880
days_of_week = pattern_data.get("DaysOfWeek", [])
7981
for day in days_of_week:
8082
self.days_of_week.append(self.days.index(day))
81-
first_day_of_week = pattern_data.get("FirstDayOfWeek", "Sunday")
82-
self.first_day_of_week = self.days.index(first_day_of_week) if first_day_of_week in self.days else 0
83+
self.first_day_of_week = self.days.index(pattern_data.get("FirstDayOfWeek", "Sunday"))
8384

8485

8586
class RecurrenceRange: # pylint: disable=too-few-public-methods
8687
"""
8788
The recurrence range settings.
8889
"""
8990

91+
type: RecurrenceRangeType
92+
end_date: Optional[datetime] = None
93+
9094
def __init__(self, range_data: Dict[str, Any]):
9195
self.type = RecurrenceRangeType.from_str(range_data.get("Type", "NoEnd"))
9296
if range_data.get("EndDate") and isinstance(range_data.get("EndDate"), str):
9397
end_date_str = range_data.get("EndDate", "")
9498
self.end_date = parsedate_to_datetime(end_date_str) if end_date_str else None
95-
self.num_of_occurrences = range_data.get("NumberOfOccurrences", 0)
99+
self.num_of_occurrences = range_data.get("NumberOfOccurrences", math.pow(2, 63) - 1)
96100
if self.num_of_occurrences < 0:
97101
raise ValueError("The number of occurrences must be greater than or equal to 0.")
98102

featuremanagement/_time_window_filter/_recurrence_evaluator.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from ._models import RecurrencePatternType, RecurrenceRangeType, TimeWindowFilterSettings, OccurrenceInfo
99
from ._recurrence_validator import validate_settings
1010

11+
DAYS_PER_WEEK = 7
1112

1213
def is_match(settings: TimeWindowFilterSettings, now: datetime) -> bool:
1314
"""
@@ -36,8 +37,10 @@ def _get_previous_occurrence(settings: TimeWindowFilterSettings, now: datetime)
3637
pattern_type = settings.recurrence.pattern.type
3738
if pattern_type == RecurrencePatternType.DAILY:
3839
occurrence_info = _get_daily_previous_occurrence(settings, now)
39-
else:
40+
elif pattern_type == RecurrencePatternType.WEEKLY:
4041
occurrence_info = _get_weekly_previous_occurrence(settings, now)
42+
else:
43+
raise ValueError(f"Invalid recurrence pattern type: %s", pattern_type)
4144

4245
recurrence_range = settings.recurrence.range
4346
range_type = recurrence_range.type
@@ -74,16 +77,16 @@ def _get_weekly_previous_occurrence(settings: TimeWindowFilterSettings, now: dat
7477
start = settings.start
7578
first_day_of_first_week = start - timedelta(days=_get_passed_week_days(start.weekday(), pattern.first_day_of_week))
7679

77-
number_of_interval = (now - first_day_of_first_week).days // (interval * 7)
80+
number_of_interval = (now - first_day_of_first_week).days // (interval * DAYS_PER_WEEK)
7881
first_day_of_most_recent_occurring_week = first_day_of_first_week + timedelta(
79-
days=number_of_interval * (interval * 7)
82+
days=number_of_interval * (interval * DAYS_PER_WEEK)
8083
)
8184
sorted_days_of_week = _sort_days_of_week(pattern.days_of_week, pattern.first_day_of_week)
8285
max_day_offset = _get_passed_week_days(sorted_days_of_week[-1], pattern.first_day_of_week)
8386
min_day_offset = _get_passed_week_days(sorted_days_of_week[0], pattern.first_day_of_week)
8487
num_of_occurrences = number_of_interval * len(sorted_days_of_week) - sorted_days_of_week.index(start.weekday())
8588

86-
if now > first_day_of_most_recent_occurring_week + timedelta(days=7):
89+
if now > first_day_of_most_recent_occurring_week + timedelta(days=DAYS_PER_WEEK):
8790
num_of_occurrences += len(sorted_days_of_week)
8891
most_recent_occurrence = first_day_of_most_recent_occurring_week + timedelta(days=max_day_offset)
8992
return OccurrenceInfo(most_recent_occurrence, num_of_occurrences)
@@ -94,7 +97,7 @@ def _get_weekly_previous_occurrence(settings: TimeWindowFilterSettings, now: dat
9497
day_with_min_offset = start
9598
if now < day_with_min_offset:
9699
most_recent_occurrence = (
97-
first_day_of_most_recent_occurring_week - timedelta(days=interval * 7) + timedelta(days=max_day_offset)
100+
first_day_of_most_recent_occurring_week - timedelta(days=interval * DAYS_PER_WEEK) + timedelta(days=max_day_offset)
98101
)
99102
else:
100103
most_recent_occurrence = day_with_min_offset
@@ -113,7 +116,14 @@ def _get_weekly_previous_occurrence(settings: TimeWindowFilterSettings, now: dat
113116

114117

115118
def _get_passed_week_days(current_day: int, first_day_of_week: int) -> int:
116-
return (current_day - first_day_of_week + 7) % 7
119+
"""
120+
Get the number of days passed since the first day of the week.
121+
:param int current_day: The current day of the week (0-6).
122+
:param int first_day_of_week: The first day of the week (0-6).
123+
:return: The number of days passed since the first day of the week.
124+
:rtype: int
125+
"""
126+
return (current_day - first_day_of_week + DAYS_PER_WEEK) % DAYS_PER_WEEK
117127

118128

119129
def _sort_days_of_week(days_of_week: List[int], first_day_of_week: int) -> List[int]:

featuremanagement/_time_window_filter/_recurrence_validator.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# license information.
55
# -------------------------------------------------------------------------
66
from datetime import datetime, timedelta
7-
from typing import List
87
from ._models import RecurrencePatternType, RecurrenceRangeType, TimeWindowFilterSettings
8+
from ._recurrence_evaluator import _get_passed_week_days, _sort_days_of_week
99

1010

1111
DAYS_PER_WEEK = 7
@@ -151,12 +151,3 @@ def _is_duration_compliant_with_days_of_week(settings: TimeWindowFilterSettings)
151151

152152
time_window_duration = settings.end - settings.start
153153
return min_gap >= time_window_duration
154-
155-
156-
def _get_passed_week_days(today: int, first_day_of_week: int) -> int:
157-
return (today - first_day_of_week + DAYS_PER_WEEK) % DAYS_PER_WEEK
158-
159-
160-
def _sort_days_of_week(days_of_week: List[int], first_day_of_week: int) -> List[int]:
161-
sorted_days = sorted(days_of_week, key=lambda day: _get_passed_week_days(day, first_day_of_week))
162-
return sorted_days

0 commit comments

Comments
 (0)