anemoi-datasets 0.5.16__py3-none-any.whl → 0.5.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- anemoi/datasets/__init__.py +4 -1
- anemoi/datasets/__main__.py +12 -2
- anemoi/datasets/_version.py +9 -4
- anemoi/datasets/commands/cleanup.py +17 -2
- anemoi/datasets/commands/compare.py +18 -2
- anemoi/datasets/commands/copy.py +196 -14
- anemoi/datasets/commands/create.py +50 -7
- anemoi/datasets/commands/finalise-additions.py +17 -2
- anemoi/datasets/commands/finalise.py +17 -2
- anemoi/datasets/commands/init-additions.py +17 -2
- anemoi/datasets/commands/init.py +16 -2
- anemoi/datasets/commands/inspect.py +283 -62
- anemoi/datasets/commands/load-additions.py +16 -2
- anemoi/datasets/commands/load.py +16 -2
- anemoi/datasets/commands/patch.py +17 -2
- anemoi/datasets/commands/publish.py +17 -2
- anemoi/datasets/commands/scan.py +31 -3
- anemoi/datasets/compute/recentre.py +47 -11
- anemoi/datasets/create/__init__.py +612 -85
- anemoi/datasets/create/check.py +142 -20
- anemoi/datasets/create/chunks.py +64 -4
- anemoi/datasets/create/config.py +185 -21
- anemoi/datasets/create/filter.py +50 -0
- anemoi/datasets/create/filters/__init__.py +33 -0
- anemoi/datasets/create/filters/empty.py +37 -0
- anemoi/datasets/create/filters/legacy.py +93 -0
- anemoi/datasets/create/filters/noop.py +37 -0
- anemoi/datasets/create/filters/orog_to_z.py +58 -0
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_relative_humidity_to_specific_humidity.py +33 -10
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_specific_humidity_to_relative_humidity.py +32 -8
- anemoi/datasets/create/filters/rename.py +205 -0
- anemoi/datasets/create/{functions/filters → filters}/rotate_winds.py +43 -28
- anemoi/datasets/create/{functions/filters → filters}/single_level_dewpoint_to_relative_humidity.py +32 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_dewpoint.py +33 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_specific_humidity.py +55 -7
- anemoi/datasets/create/{functions/filters → filters}/single_level_specific_humidity_to_relative_humidity.py +98 -37
- anemoi/datasets/create/filters/speeddir_to_uv.py +95 -0
- anemoi/datasets/create/{functions/filters → filters}/sum.py +24 -27
- anemoi/datasets/create/filters/transform.py +53 -0
- anemoi/datasets/create/{functions/filters → filters}/unrotate_winds.py +27 -18
- anemoi/datasets/create/filters/uv_to_speeddir.py +94 -0
- anemoi/datasets/create/{functions/filters → filters}/wz_to_w.py +51 -33
- anemoi/datasets/create/input/__init__.py +76 -5
- anemoi/datasets/create/input/action.py +149 -13
- anemoi/datasets/create/input/concat.py +81 -10
- anemoi/datasets/create/input/context.py +39 -4
- anemoi/datasets/create/input/data_sources.py +72 -6
- anemoi/datasets/create/input/empty.py +21 -3
- anemoi/datasets/create/input/filter.py +60 -12
- anemoi/datasets/create/input/function.py +154 -37
- anemoi/datasets/create/input/join.py +86 -14
- anemoi/datasets/create/input/misc.py +67 -17
- anemoi/datasets/create/input/pipe.py +33 -6
- anemoi/datasets/create/input/repeated_dates.py +189 -41
- anemoi/datasets/create/input/result.py +202 -87
- anemoi/datasets/create/input/step.py +119 -22
- anemoi/datasets/create/input/template.py +100 -13
- anemoi/datasets/create/input/trace.py +62 -7
- anemoi/datasets/create/patch.py +52 -4
- anemoi/datasets/create/persistent.py +134 -17
- anemoi/datasets/create/size.py +15 -1
- anemoi/datasets/create/source.py +51 -0
- anemoi/datasets/create/sources/__init__.py +36 -0
- anemoi/datasets/create/{functions/sources → sources}/accumulations.py +296 -30
- anemoi/datasets/create/{functions/sources → sources}/constants.py +27 -2
- anemoi/datasets/create/{functions/sources → sources}/eccc_fstd.py +7 -3
- anemoi/datasets/create/sources/empty.py +37 -0
- anemoi/datasets/create/{functions/sources → sources}/forcings.py +25 -1
- anemoi/datasets/create/sources/grib.py +297 -0
- anemoi/datasets/create/{functions/sources → sources}/hindcasts.py +38 -4
- anemoi/datasets/create/sources/legacy.py +93 -0
- anemoi/datasets/create/{functions/sources → sources}/mars.py +168 -20
- anemoi/datasets/create/sources/netcdf.py +42 -0
- anemoi/datasets/create/sources/opendap.py +43 -0
- anemoi/datasets/create/{functions/sources/__init__.py → sources/patterns.py} +35 -4
- anemoi/datasets/create/sources/recentre.py +150 -0
- anemoi/datasets/create/{functions/sources → sources}/source.py +27 -5
- anemoi/datasets/create/{functions/sources → sources}/tendencies.py +64 -7
- anemoi/datasets/create/sources/xarray.py +92 -0
- anemoi/datasets/create/sources/xarray_kerchunk.py +36 -0
- anemoi/datasets/create/sources/xarray_support/README.md +1 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/__init__.py +109 -8
- anemoi/datasets/create/sources/xarray_support/coordinates.py +442 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/field.py +94 -16
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/fieldlist.py +90 -25
- anemoi/datasets/create/sources/xarray_support/flavour.py +1036 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/grid.py +92 -31
- anemoi/datasets/create/sources/xarray_support/metadata.py +395 -0
- anemoi/datasets/create/sources/xarray_support/patch.py +91 -0
- anemoi/datasets/create/sources/xarray_support/time.py +391 -0
- anemoi/datasets/create/sources/xarray_support/variable.py +331 -0
- anemoi/datasets/create/sources/xarray_zarr.py +41 -0
- anemoi/datasets/create/{functions/sources → sources}/zenodo.py +34 -5
- anemoi/datasets/create/statistics/__init__.py +233 -44
- anemoi/datasets/create/statistics/summary.py +52 -6
- anemoi/datasets/create/testing.py +76 -0
- anemoi/datasets/create/{functions/filters/noop.py → typing.py} +6 -3
- anemoi/datasets/create/utils.py +97 -6
- anemoi/datasets/create/writer.py +26 -4
- anemoi/datasets/create/zarr.py +170 -23
- anemoi/datasets/data/__init__.py +51 -4
- anemoi/datasets/data/complement.py +191 -40
- anemoi/datasets/data/concat.py +141 -16
- anemoi/datasets/data/dataset.py +558 -62
- anemoi/datasets/data/debug.py +197 -26
- anemoi/datasets/data/ensemble.py +93 -8
- anemoi/datasets/data/fill_missing.py +165 -18
- anemoi/datasets/data/forwards.py +428 -56
- anemoi/datasets/data/grids.py +323 -97
- anemoi/datasets/data/indexing.py +112 -19
- anemoi/datasets/data/interpolate.py +92 -12
- anemoi/datasets/data/join.py +158 -19
- anemoi/datasets/data/masked.py +129 -15
- anemoi/datasets/data/merge.py +137 -23
- anemoi/datasets/data/misc.py +172 -16
- anemoi/datasets/data/missing.py +233 -29
- anemoi/datasets/data/rescale.py +111 -10
- anemoi/datasets/data/select.py +168 -26
- anemoi/datasets/data/statistics.py +67 -6
- anemoi/datasets/data/stores.py +149 -64
- anemoi/datasets/data/subset.py +159 -25
- anemoi/datasets/data/unchecked.py +168 -57
- anemoi/datasets/data/xy.py +168 -25
- anemoi/datasets/dates/__init__.py +191 -16
- anemoi/datasets/dates/groups.py +189 -47
- anemoi/datasets/grids.py +270 -31
- anemoi/datasets/testing.py +28 -1
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/METADATA +9 -6
- anemoi_datasets-0.5.18.dist-info/RECORD +137 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/WHEEL +1 -1
- anemoi/datasets/create/functions/__init__.py +0 -66
- anemoi/datasets/create/functions/filters/__init__.py +0 -9
- anemoi/datasets/create/functions/filters/empty.py +0 -17
- anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
- anemoi/datasets/create/functions/filters/rename.py +0 -79
- anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
- anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
- anemoi/datasets/create/functions/sources/empty.py +0 -15
- anemoi/datasets/create/functions/sources/grib.py +0 -150
- anemoi/datasets/create/functions/sources/netcdf.py +0 -15
- anemoi/datasets/create/functions/sources/opendap.py +0 -15
- anemoi/datasets/create/functions/sources/recentre.py +0 -60
- anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
- anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
- anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
- anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
- anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
- anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
- anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
- anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
- anemoi/datasets/utils/fields.py +0 -47
- anemoi_datasets-0.5.16.dist-info/RECORD +0 -129
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/entry_points.txt +0 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info/licenses}/LICENSE +0 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/top_level.txt +0 -0
anemoi/datasets/dates/groups.py
CHANGED
|
@@ -8,14 +8,31 @@
|
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
import datetime
|
|
11
12
|
import itertools
|
|
13
|
+
from abc import ABC
|
|
14
|
+
from abc import abstractmethod
|
|
12
15
|
from functools import cached_property
|
|
16
|
+
from typing import Any
|
|
17
|
+
from typing import Callable
|
|
18
|
+
from typing import Iterator
|
|
19
|
+
from typing import List
|
|
20
|
+
from typing import Tuple
|
|
21
|
+
from typing import Union
|
|
13
22
|
|
|
14
23
|
from anemoi.datasets.dates import DatesProvider
|
|
15
24
|
from anemoi.datasets.dates import as_datetime
|
|
16
25
|
|
|
17
26
|
|
|
18
|
-
def _shorten(dates):
|
|
27
|
+
def _shorten(dates: Union[List[datetime.datetime], Tuple[datetime.datetime, ...]]) -> Union[str, List[str]]:
|
|
28
|
+
"""Shorten the list of dates for display.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
dates (Union[List[datetime.datetime], Tuple[datetime.datetime, ...]]): The list of dates.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Union[str, List[str]]: The shortened list of dates.
|
|
35
|
+
"""
|
|
19
36
|
if isinstance(dates, (list, tuple)):
|
|
20
37
|
dates = [d.isoformat() for d in dates]
|
|
21
38
|
if len(dates) > 5:
|
|
@@ -24,7 +41,9 @@ def _shorten(dates):
|
|
|
24
41
|
|
|
25
42
|
|
|
26
43
|
class GroupOfDates:
|
|
27
|
-
|
|
44
|
+
"""A class to represent a group of dates."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, dates: List[datetime.datetime], provider: DatesProvider, partial_ok: bool = False) -> None:
|
|
28
47
|
assert isinstance(provider, DatesProvider), type(provider)
|
|
29
48
|
assert isinstance(dates, list)
|
|
30
49
|
|
|
@@ -32,68 +51,115 @@ class GroupOfDates:
|
|
|
32
51
|
self.provider = provider
|
|
33
52
|
self.partial_ok = partial_ok
|
|
34
53
|
|
|
35
|
-
def __len__(self):
|
|
54
|
+
def __len__(self) -> int:
|
|
55
|
+
"""Return the number of dates in the group.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
int: The number of dates.
|
|
59
|
+
"""
|
|
36
60
|
return len(self.dates)
|
|
37
61
|
|
|
38
|
-
def __iter__(self):
|
|
62
|
+
def __iter__(self) -> Iterator[datetime.datetime]:
|
|
63
|
+
"""Return an iterator over the dates in the group.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Iterator[datetime.datetime]: The iterator over the dates.
|
|
67
|
+
"""
|
|
39
68
|
return iter(self.dates)
|
|
40
69
|
|
|
41
70
|
def __repr__(self) -> str:
|
|
71
|
+
"""Return a string representation of the group of dates.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
str: The string representation.
|
|
75
|
+
"""
|
|
42
76
|
return f"GroupOfDates(dates={_shorten(self.dates)})"
|
|
43
77
|
|
|
44
78
|
def __eq__(self, other: object) -> bool:
|
|
79
|
+
"""Check if two groups of dates are equal.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
other (object): The other group of dates.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
bool: True if the groups are equal, False otherwise.
|
|
86
|
+
"""
|
|
45
87
|
return isinstance(other, GroupOfDates) and self.dates == other.dates
|
|
46
88
|
|
|
47
89
|
|
|
48
90
|
class Groups:
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
91
|
+
"""A collection of groups of dates.
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
>>> list(Groups(group_by="daily", start="2023-01-01 00:00", end="2023-01-05 00:00", frequency=12))[0]
|
|
95
|
+
[datetime.datetime(2023, 1, 1, 0, 0), datetime.datetime(2023, 1, 1, 12, 0)]
|
|
96
|
+
|
|
97
|
+
>>> list(Groups(group_by="daily", start="2023-01-01 00:00", end="2023-01-05 00:00", frequency=12))[1]
|
|
98
|
+
[datetime.datetime(2023, 1, 2, 0, 0), datetime.datetime(2023, 1, 2, 12, 0)]
|
|
99
|
+
|
|
100
|
+
>>> g = Groups(group_by=3, start="2023-01-01 00:00", end="2023-01-05 00:00", frequency=24)
|
|
101
|
+
>>> len(list(g))
|
|
102
|
+
2
|
|
103
|
+
>>> len(list(g)[0])
|
|
104
|
+
3
|
|
105
|
+
>>> len(list(g)[1])
|
|
106
|
+
2
|
|
107
|
+
>>> g = Groups(group_by=3,
|
|
108
|
+
... start="2023-01-01 00:00",
|
|
109
|
+
... end="2023-01-05 00:00",
|
|
110
|
+
... frequency=24,
|
|
111
|
+
... missing=["2023-01-02 00:00"])
|
|
112
|
+
>>> len(list(g))
|
|
113
|
+
2
|
|
114
|
+
>>> len(list(g)[0])
|
|
115
|
+
2
|
|
116
|
+
>>> len(list(g)[1])
|
|
117
|
+
2
|
|
73
118
|
"""
|
|
74
119
|
|
|
75
|
-
def __init__(self, **kwargs):
|
|
120
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
121
|
+
"""Initialize the class with the provided keyword arguments.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
**kwargs : Any : Arbitrary keyword arguments. Expected keys include:
|
|
126
|
+
- group_by: Configuration for the Grouper.
|
|
127
|
+
- Other keys for DatesProvider configuration.
|
|
128
|
+
"""
|
|
129
|
+
|
|
76
130
|
group_by = kwargs.pop("group_by")
|
|
77
131
|
self._dates = DatesProvider.from_config(**kwargs)
|
|
78
132
|
self._grouper = Grouper.from_config(group_by)
|
|
79
133
|
self._filter = Filter(self._dates.missing)
|
|
80
134
|
|
|
81
135
|
@property
|
|
82
|
-
def provider(self):
|
|
136
|
+
def provider(self) -> DatesProvider:
|
|
137
|
+
"""Return the dates provider."""
|
|
83
138
|
return self._dates
|
|
84
139
|
|
|
85
|
-
def __iter__(self):
|
|
140
|
+
def __iter__(self) -> Iterator[GroupOfDates]:
|
|
141
|
+
"""Return an iterator over the groups of dates.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
145
|
+
"""
|
|
86
146
|
for go in self._grouper(self._dates):
|
|
87
147
|
dates = self._filter(go.dates)
|
|
88
148
|
if not dates:
|
|
89
149
|
continue
|
|
90
150
|
yield GroupOfDates(dates, go.provider)
|
|
91
151
|
|
|
92
|
-
def __len__(self):
|
|
152
|
+
def __len__(self) -> int:
|
|
153
|
+
"""Return the number of groups of dates.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
int: The number of groups.
|
|
157
|
+
"""
|
|
93
158
|
return self._len
|
|
94
159
|
|
|
95
160
|
@cached_property
|
|
96
|
-
def _len(self):
|
|
161
|
+
def _len(self) -> int:
|
|
162
|
+
"""Calculate the number of groups of dates."""
|
|
97
163
|
n = 0
|
|
98
164
|
for go in self._grouper(self._dates):
|
|
99
165
|
dates = self._filter(go.dates)
|
|
@@ -102,28 +168,56 @@ class Groups:
|
|
|
102
168
|
n += 1
|
|
103
169
|
return n
|
|
104
170
|
|
|
105
|
-
def __repr__(self):
|
|
171
|
+
def __repr__(self) -> str:
|
|
172
|
+
"""Return a string representation of the groups of dates.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
str: The string representation.
|
|
176
|
+
"""
|
|
106
177
|
return f"{self.__class__.__name__}(dates={len(self)},{_shorten(self._dates)})"
|
|
107
178
|
|
|
108
|
-
def describe(self):
|
|
109
|
-
|
|
179
|
+
def describe(self) -> str:
|
|
180
|
+
"""Return a summary description of the dates.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
str: The summary description.
|
|
184
|
+
"""
|
|
185
|
+
return self._dates.summary
|
|
186
|
+
|
|
187
|
+
def one_date(self) -> GroupOfDates:
|
|
188
|
+
"""Return a group containing only one date.
|
|
110
189
|
|
|
111
|
-
|
|
190
|
+
Returns:
|
|
191
|
+
GroupOfDates: The group containing only one date.
|
|
192
|
+
"""
|
|
112
193
|
go = next(iter(self))
|
|
113
194
|
return GroupOfDates([go.dates[0]], go.provider)
|
|
114
195
|
|
|
115
196
|
|
|
116
197
|
class Filter:
|
|
117
|
-
|
|
198
|
+
"""A class to filter out missing dates."""
|
|
199
|
+
|
|
200
|
+
def __init__(self, missing: List[datetime.datetime]) -> None:
|
|
118
201
|
self.missing = set(as_datetime(m) for m in missing)
|
|
119
202
|
|
|
120
|
-
def __call__(self, dates):
|
|
203
|
+
def __call__(self, dates: List[datetime.datetime]) -> List[datetime.datetime]:
|
|
204
|
+
"""Filter out missing dates from the list of dates.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
dates (List[datetime.datetime]): The list of dates.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
List[datetime.datetime]: The filtered list of dates.
|
|
211
|
+
"""
|
|
121
212
|
return [d for d in dates if d not in self.missing]
|
|
122
213
|
|
|
123
214
|
|
|
124
|
-
class Grouper:
|
|
215
|
+
class Grouper(ABC):
|
|
216
|
+
"""Abstract base class for grouping dates."""
|
|
217
|
+
|
|
125
218
|
@classmethod
|
|
126
|
-
def from_config(cls, group_by):
|
|
219
|
+
def from_config(cls, group_by: Any) -> "Grouper":
|
|
220
|
+
"""Create a grouper based on the configuration."""
|
|
127
221
|
|
|
128
222
|
if isinstance(group_by, int) and group_by > 0:
|
|
129
223
|
return GrouperByFixedSize(group_by)
|
|
@@ -142,9 +236,31 @@ class Grouper:
|
|
|
142
236
|
}[group_by]
|
|
143
237
|
return GrouperByKey(key)
|
|
144
238
|
|
|
239
|
+
@abstractmethod
|
|
240
|
+
def __call__(self, dates: DatesProvider) -> Iterator[GroupOfDates]:
|
|
241
|
+
"""Group dates based on the implementation.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
dates (DatesProvider): The dates provider.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
248
|
+
"""
|
|
249
|
+
pass
|
|
250
|
+
|
|
145
251
|
|
|
146
252
|
class ReferenceDateGroup(Grouper):
|
|
147
|
-
|
|
253
|
+
"""Group dates by their reference date."""
|
|
254
|
+
|
|
255
|
+
def __call__(self, dates: DatesProvider) -> Iterator[GroupOfDates]:
|
|
256
|
+
"""Group dates by their reference date.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
dates (DatesProvider): The dates provider.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
263
|
+
"""
|
|
148
264
|
assert isinstance(dates, DatesProvider), type(dates)
|
|
149
265
|
|
|
150
266
|
mapping = dates.mapping
|
|
@@ -157,7 +273,17 @@ class ReferenceDateGroup(Grouper):
|
|
|
157
273
|
|
|
158
274
|
|
|
159
275
|
class GrouperOneGroup(Grouper):
|
|
160
|
-
|
|
276
|
+
"""Group all dates into a single group."""
|
|
277
|
+
|
|
278
|
+
def __call__(self, dates: DatesProvider) -> Iterator[GroupOfDates]:
|
|
279
|
+
"""Group all dates into a single group.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
dates (DatesProvider): The dates provider.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
286
|
+
"""
|
|
161
287
|
assert isinstance(dates, DatesProvider), type(dates)
|
|
162
288
|
|
|
163
289
|
yield GroupOfDates(dates.values, dates)
|
|
@@ -166,10 +292,18 @@ class GrouperOneGroup(Grouper):
|
|
|
166
292
|
class GrouperByKey(Grouper):
|
|
167
293
|
"""Group dates by a key."""
|
|
168
294
|
|
|
169
|
-
def __init__(self, key):
|
|
295
|
+
def __init__(self, key: Callable[[datetime.datetime], Any]) -> None:
|
|
170
296
|
self.key = key
|
|
171
297
|
|
|
172
|
-
def __call__(self, dates):
|
|
298
|
+
def __call__(self, dates: DatesProvider) -> Iterator[GroupOfDates]:
|
|
299
|
+
"""Group dates based on the provided key.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
dates (DatesProvider): The dates provider.
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
306
|
+
"""
|
|
173
307
|
for _, g in itertools.groupby(sorted(dates, key=self.key), key=self.key):
|
|
174
308
|
yield GroupOfDates(list(g), dates)
|
|
175
309
|
|
|
@@ -177,10 +311,18 @@ class GrouperByKey(Grouper):
|
|
|
177
311
|
class GrouperByFixedSize(Grouper):
|
|
178
312
|
"""Group dates by a fixed size."""
|
|
179
313
|
|
|
180
|
-
def __init__(self, size):
|
|
314
|
+
def __init__(self, size: int) -> None:
|
|
181
315
|
self.size = size
|
|
182
316
|
|
|
183
|
-
def __call__(self, dates):
|
|
317
|
+
def __call__(self, dates: DatesProvider) -> Iterator[GroupOfDates]:
|
|
318
|
+
"""Group dates into fixed-size batches.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
dates (DatesProvider): The dates provider.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
Iterator[GroupOfDates]: The iterator over the groups of dates.
|
|
325
|
+
"""
|
|
184
326
|
batch = []
|
|
185
327
|
|
|
186
328
|
for d in dates:
|