-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsprint.py
146 lines (122 loc) · 5.07 KB
/
sprint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import datetime
import dateutil.parser
import falcon
import features
import middleware.auth
import yp
def current_sprint(
sprints: list[yp.Sprint],
offset: int=0,
ref_date: datetime.datetime=None,
):
'''
returns the "current sprint" from the given list of sprints. The list of sprints is
assumed to be ordered chronologically, with the newest one being at the beginning.
the current sprint is determined as the one precedeeding the newest sprint whose
end-date is in the past (compared to "today" according to system-time or passed-in
reference-date). If the end-date of a sprint is identical to "today" (or reference-date), it
is considered to still be the current sprint.
if offset is set, the sprint returned is calculated relative (in full sprints) to the current
one. For example, an offset of +1 will return the next sprint, whereas -1 will return the
previous one.
note that date-operations are not timezone-aware, which is believed to be "good enough"
'''
if not ref_date:
ref_date = datetime.datetime.today()
if offset: # need to invert offset, as sprints are ordered chronologically
offset = - offset
for idx, sprint in enumerate(sprints):
if sprint.end_date.date() > ref_date.date():
continue
if sprint.end_date.date() == ref_date.date():
return sprint
# if this line is reached, current sprint has already ended, so its predecessor is the
# current one (edge-case: there is no such sprint)
if idx == 0:
# pylint: disable=E1101
raise falcon.HTTPBadRequest(
title='no sprint found',
description=f'all sprints ended before {ref_date.date()=}',
)
return sprints[idx - 1 + offset]
# pylint: disable=E1101
raise falcon.HTTPBadRequest(
title='no sprint found',
description=f'all sprints started after {ref_date=}',
)
@middleware.auth.noauth
class SprintInfos:
required_features = (features.FeatureSprints,)
def __init__(
self,
sprints_repo_callback,
sprints_relpath_callback,
sprint_date_display_name_callback,
):
self.sprints_repo_callback = sprints_repo_callback
self.sprints_relpath_callback = sprints_relpath_callback
self.sprint_date_display_name_callback = sprint_date_display_name_callback
def on_get(self, req, resp):
sprints = yp._sprints(
repo=self.sprints_repo_callback(),
sprints_file_relpath=self.sprints_relpath_callback(),
)
sprints_meta = yp._sprints_metadata(
repo=self.sprints_repo_callback(),
sprints_file_relpath=self.sprints_relpath_callback(),
)
resp.media = {
'sprints': [
sprint.asdict(
sprint_date_display_name_callback=self.sprint_date_display_name_callback,
meta=sprints_meta,
)
for sprint in sprints
]
}
def on_get_current(self, req: falcon.Request, resp):
'''
returns the "current" sprint infos, optionally considering passed query-params.
The current sprint is (by default, i.e. no arguments) the sprint whose end_date is either
the current day, or the nearest day (in chronological sense) from today, considering only
future sprints.
**expected query parameters:**
offset: <int>; if set, the returned sprint is offset by given amount of sprints \n
(positive value will yield future sprints, while negative numbers will yield \n
past ones) \n
before: <str(iso8601-date)>; if set, the returned sprint is calculated setting "today" \n
to the specified date
If both `offset` and `before` are given, offset is applied after calculating "current"
sprint.
**response:**
name: <str> e.g. "2304b" \n
dates: \n
- name: <str> e.g. "rtc" \n
display_name: <str> e.g. "Release To Customer" \n
value: <iso8601-date-str> \n
'''
sprints = yp._sprints(
repo=self.sprints_repo_callback(),
sprints_file_relpath=self.sprints_relpath_callback(),
)
sprints_meta = yp._sprints_metadata(
repo=self.sprints_repo_callback(),
sprints_file_relpath=self.sprints_relpath_callback(),
)
offset = req.get_param_as_int('offset', default=0)
before = req.get_param('before')
if before:
try:
before = dateutil.parser.isoparse(before)
except ValueError:
# pylint: disable=E1101
raise falcon.HTTPBadRequest(title='invalid date format')
current = current_sprint(
sprints=sprints,
offset=offset,
ref_date=before,
)
resp.media = current.asdict(
sprint_date_display_name_callback=self.sprint_date_display_name_callback,
meta=sprints_meta,
)