Skip to content

Commit 895a7a1

Browse files
committed
JIT: minor code clean
1 parent 0eb888f commit 895a7a1

File tree

6 files changed

+82
-45
lines changed

6 files changed

+82
-45
lines changed

src/server/_validate.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,13 @@ def push_range(first: str, last: str):
189189
values.append(parse_date(part))
190190
# success, return the list
191191
return values
192+
193+
def extract_bool(key: Union[str, Sequence[str]]) -> Optional[bool]:
194+
s = _extract_value(key)
195+
if not s:
196+
return None
197+
if s.lower() == "true":
198+
return True
199+
if s.lower() == "false":
200+
return False
201+
raise ValidationFailedException(f"{key}: not a boolean: {s}")

src/server/endpoints/covidcast.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from .._query import QueryBuilder, execute_query, run_query, parse_row, filter_fields
3131
from .._printer import create_printer, CSVPrinter
3232
from .._validate import (
33+
extract_bool,
3334
extract_date,
3435
extract_dates,
3536
extract_integer,
@@ -122,14 +123,23 @@ def _handle_lag_issues_as_of(q: QueryBuilder, issues: Optional[List[Union[Tuple[
122123
pass
123124

124125

125-
# TODO: Write an actual smoother arg parser.
126126
def parse_transform_args():
127127
# The length of the window to smooth over.
128-
smoother_window_length = request.values.get("smoother_window_length", 7)
128+
smoother_window_length = extract_integer("smoother_window_length")
129+
if smoother_window_length is None:
130+
smoother_window_length = 7
131+
132+
# TODO: Add support for floats inputs here.
129133
# The value to fill for missing date values.
130-
pad_fill_value = request.values.get("pad_fill_value", nan)
134+
pad_fill_value = extract_integer("pad_fill_value")
135+
if pad_fill_value is None:
136+
pad_fill_value = nan
137+
131138
# The value to fill for None or nan values.
132-
nan_fill_value = request.values.get("nans_fill_value", nan)
139+
nan_fill_value = extract_integer("nans_fill_value")
140+
if nan_fill_value is None:
141+
nan_fill_value = nan
142+
133143
smoother_args = {
134144
"smoother_kernel": SmootherKernelValue.average,
135145
"smoother_window_length": smoother_window_length if isinstance(smoother_window_length, Number) and smoother_window_length <= MAX_SMOOTHER_WINDOW else MAX_SMOOTHER_WINDOW,
@@ -140,8 +150,11 @@ def parse_transform_args():
140150

141151

142152
def parse_jit_bypass():
143-
jit_bypass = request.values.get("jit_bypass")
144-
return bool(jit_bypass) if jit_bypass else False
153+
jit_bypass = extract_bool("jit_bypass")
154+
if jit_bypass is None:
155+
return False
156+
else:
157+
return jit_bypass
145158

146159

147160
@bp.route("/", methods=("GET", "POST"))

src/server/endpoints/covidcast_utils/model.py

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from dataclasses import asdict, dataclass, field
2-
from datetime import timedelta
32
from enum import Enum
43
from functools import partial
54
from itertools import groupby, repeat, tee
@@ -15,7 +14,7 @@
1514
from delphi_utils.nancodes import Nans
1615
from ..._params import SourceSignalPair, TimePair
1716
from .smooth_diff import generate_smoothed_rows, generate_diffed_rows
18-
from ...utils import date_to_time_value, shift_time_value, time_value_to_date, time_value_range
17+
from ...utils import shift_time_value, iterate_over_ints_and_ranges
1918

2019

2120
IDENTITY: Callable = lambda rows, **kwargs: rows
@@ -491,35 +490,6 @@ def pad_time_window(time_window: Tuple[int, int], pad_length: int) -> Tuple[int,
491490
return (shift_time_value(min_time, -1 * pad_length), max_time)
492491

493492

494-
def _iterate_over_ints_and_ranges(lst: Iterator[Union[int, Tuple[int, int]]], use_dates: bool = True) -> Iterator[int]:
495-
"""A generator that iterates over the unique values in a list of integers and ranges in ascending order.
496-
497-
The tuples are assumed to be left- and right-inclusive. If use_dates is True, then the integers are interpreted as
498-
YYYYMMDD dates.
499-
500-
Examples:
501-
iterate_over_ints_and_ranges([(5, 8), 0]) would iterate over [0, 5, 6, 7, 8].
502-
iterate_over_ints_and_ranges([(5, 8), (4, 6), (3, 5)]) would iterate over [3, 4, 5, 6, 7, 8].
503-
iterate_over_ints_and_ranges([(7, 8), (5, 7), (3, 8), 8]) would iterate over [3, 4, 5, 6, 7, 8].
504-
"""
505-
lst = sorted((x, x) if isinstance(x, int) else x for x in lst)
506-
if not lst:
507-
return
508-
509-
if use_dates:
510-
increment = lambda x, y: date_to_time_value(time_value_to_date(x) + timedelta(days=y))
511-
range_handler = time_value_range
512-
else:
513-
increment = lambda x, y: x + y
514-
range_handler = range
515-
516-
biggest_seen = increment(lst[0][0], -1)
517-
for a, b in lst:
518-
for y in range_handler(max(a, increment(biggest_seen, 1)), increment(b, 1)):
519-
yield y
520-
biggest_seen = max(biggest_seen, b)
521-
522-
523493
def get_day_range(time_pairs: List[TimePair]) -> Iterator[int]:
524494
"""Iterate over a list of TimePair time_values, including the values contained in the ranges.
525495
@@ -540,7 +510,7 @@ def get_day_range(time_pairs: List[TimePair]) -> Iterator[int]:
540510
else:
541511
raise ValueError("get_day_range only supports int or list time_values.")
542512

543-
return _iterate_over_ints_and_ranges(time_values_flattened)
513+
return iterate_over_ints_and_ranges(time_values_flattened)
544514

545515

546516
def _generate_transformed_rows(

src/server/utils/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
from .dates import shift_time_value, date_to_time_value, time_value_to_iso, time_value_to_date, days_in_range, weeks_in_range, shift_week_value, week_to_time_value, week_value_to_week, guess_time_value_is_day, time_values_to_ranges, days_to_ranges, weeks_to_ranges, time_value_range
1+
from .dates import (
2+
shift_time_value,
3+
date_to_time_value,
4+
time_value_to_iso,
5+
time_value_to_date,
6+
days_in_range,
7+
weeks_in_range,
8+
shift_week_value,
9+
week_to_time_value,
10+
week_value_to_week,
11+
guess_time_value_is_day,
12+
time_values_to_ranges,
13+
days_to_ranges,
14+
weeks_to_ranges,
15+
iterate_over_range,
16+
iterate_over_ints_and_ranges,
17+
)

src/server/utils/dates.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def _to_ranges(values: Sequence[Union[Tuple[int, int], int]], value_to_date: Cal
140140
logging.info('bad input to date ranges', input=values, exception=e)
141141
return values
142142

143-
def time_value_range(start: int, end: int) -> Iterator[int]:
143+
def iterate_over_range(start: int, end: int) -> Iterator[int]:
144144
"""Iterate over ints corresponding to dates in a time range.
145145
146146
Left inclusive, right exclusive to mimic behavior of Python's built-in range.
@@ -152,3 +152,31 @@ def time_value_range(start: int, end: int) -> Iterator[int]:
152152
while current_date < final_date:
153153
yield date_to_time_value(current_date)
154154
current_date = current_date + timedelta(days=1)
155+
156+
def iterate_over_ints_and_ranges(lst: Iterator[Union[int, Tuple[int, int]]], use_dates: bool = True) -> Iterator[int]:
157+
"""A generator that iterates over the unique values in a list of integers and ranges in ascending order.
158+
159+
The tuples are assumed to be left- and right-inclusive. If use_dates is True, then the integers are interpreted as
160+
YYYYMMDD dates.
161+
162+
Examples:
163+
iterate_over_ints_and_ranges([(5, 8), 0]) would iterate over [0, 5, 6, 7, 8].
164+
iterate_over_ints_and_ranges([(5, 8), (4, 6), (3, 5)]) would iterate over [3, 4, 5, 6, 7, 8].
165+
iterate_over_ints_and_ranges([(7, 8), (5, 7), (3, 8), 8]) would iterate over [3, 4, 5, 6, 7, 8].
166+
"""
167+
lst = sorted((x, x) if isinstance(x, int) else x for x in lst)
168+
if not lst:
169+
return
170+
171+
if use_dates:
172+
increment = lambda x, y: date_to_time_value(time_value_to_date(x) + timedelta(days=y))
173+
range_handler = iterate_over_range
174+
else:
175+
increment = lambda x, y: x + y
176+
range_handler = range
177+
178+
biggest_seen = increment(lst[0][0], -1)
179+
for a, b in lst:
180+
for y in range_handler(max(a, increment(biggest_seen, 1)), increment(b, 1)):
181+
yield y
182+
biggest_seen = max(biggest_seen, b)

tests/server/utils/test_dates.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from datetime import date
33
from epiweeks import Week
44

5-
from delphi.epidata.server.utils.dates import time_value_to_date, date_to_time_value, shift_time_value, time_value_to_iso, days_in_range, weeks_in_range, week_to_time_value, week_value_to_week, time_values_to_ranges, time_value_range
5+
from delphi.epidata.server.utils.dates import time_value_to_date, date_to_time_value, shift_time_value, time_value_to_iso, days_in_range, weeks_in_range, week_to_time_value, week_value_to_week, time_values_to_ranges, iterate_over_range
66

77

88
class UnitTests(unittest.TestCase):
@@ -60,7 +60,7 @@ def test_time_values_to_ranges(self):
6060
# individual weeks become a range (2020 is a rare year with 53 weeks)
6161
self.assertEqual(time_values_to_ranges([202051, 202052, 202053, 202101, 202102]), [(202051, 202102)])
6262

63-
def test_time_value_range(self):
64-
self.assertEqual(list(time_value_range(20210801, 20210805)), [20210801, 20210802, 20210803, 20210804])
65-
self.assertEqual(list(time_value_range(20210801, 20210801)), [])
66-
self.assertEqual(list(time_value_range(20210801, 20210701)), [])
63+
def test_iterate_over_range(self):
64+
self.assertEqual(list(iterate_over_range(20210801, 20210805)), [20210801, 20210802, 20210803, 20210804])
65+
self.assertEqual(list(iterate_over_range(20210801, 20210801)), [])
66+
self.assertEqual(list(iterate_over_range(20210801, 20210701)), [])

0 commit comments

Comments
 (0)