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.
Files changed (155) hide show
  1. anemoi/datasets/__init__.py +4 -1
  2. anemoi/datasets/__main__.py +12 -2
  3. anemoi/datasets/_version.py +9 -4
  4. anemoi/datasets/commands/cleanup.py +17 -2
  5. anemoi/datasets/commands/compare.py +18 -2
  6. anemoi/datasets/commands/copy.py +196 -14
  7. anemoi/datasets/commands/create.py +50 -7
  8. anemoi/datasets/commands/finalise-additions.py +17 -2
  9. anemoi/datasets/commands/finalise.py +17 -2
  10. anemoi/datasets/commands/init-additions.py +17 -2
  11. anemoi/datasets/commands/init.py +16 -2
  12. anemoi/datasets/commands/inspect.py +283 -62
  13. anemoi/datasets/commands/load-additions.py +16 -2
  14. anemoi/datasets/commands/load.py +16 -2
  15. anemoi/datasets/commands/patch.py +17 -2
  16. anemoi/datasets/commands/publish.py +17 -2
  17. anemoi/datasets/commands/scan.py +31 -3
  18. anemoi/datasets/compute/recentre.py +47 -11
  19. anemoi/datasets/create/__init__.py +612 -85
  20. anemoi/datasets/create/check.py +142 -20
  21. anemoi/datasets/create/chunks.py +64 -4
  22. anemoi/datasets/create/config.py +185 -21
  23. anemoi/datasets/create/filter.py +50 -0
  24. anemoi/datasets/create/filters/__init__.py +33 -0
  25. anemoi/datasets/create/filters/empty.py +37 -0
  26. anemoi/datasets/create/filters/legacy.py +93 -0
  27. anemoi/datasets/create/filters/noop.py +37 -0
  28. anemoi/datasets/create/filters/orog_to_z.py +58 -0
  29. anemoi/datasets/create/{functions/filters → filters}/pressure_level_relative_humidity_to_specific_humidity.py +33 -10
  30. anemoi/datasets/create/{functions/filters → filters}/pressure_level_specific_humidity_to_relative_humidity.py +32 -8
  31. anemoi/datasets/create/filters/rename.py +205 -0
  32. anemoi/datasets/create/{functions/filters → filters}/rotate_winds.py +43 -28
  33. anemoi/datasets/create/{functions/filters → filters}/single_level_dewpoint_to_relative_humidity.py +32 -9
  34. anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_dewpoint.py +33 -9
  35. anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_specific_humidity.py +55 -7
  36. anemoi/datasets/create/{functions/filters → filters}/single_level_specific_humidity_to_relative_humidity.py +98 -37
  37. anemoi/datasets/create/filters/speeddir_to_uv.py +95 -0
  38. anemoi/datasets/create/{functions/filters → filters}/sum.py +24 -27
  39. anemoi/datasets/create/filters/transform.py +53 -0
  40. anemoi/datasets/create/{functions/filters → filters}/unrotate_winds.py +27 -18
  41. anemoi/datasets/create/filters/uv_to_speeddir.py +94 -0
  42. anemoi/datasets/create/{functions/filters → filters}/wz_to_w.py +51 -33
  43. anemoi/datasets/create/input/__init__.py +76 -5
  44. anemoi/datasets/create/input/action.py +149 -13
  45. anemoi/datasets/create/input/concat.py +81 -10
  46. anemoi/datasets/create/input/context.py +39 -4
  47. anemoi/datasets/create/input/data_sources.py +72 -6
  48. anemoi/datasets/create/input/empty.py +21 -3
  49. anemoi/datasets/create/input/filter.py +60 -12
  50. anemoi/datasets/create/input/function.py +154 -37
  51. anemoi/datasets/create/input/join.py +86 -14
  52. anemoi/datasets/create/input/misc.py +67 -17
  53. anemoi/datasets/create/input/pipe.py +33 -6
  54. anemoi/datasets/create/input/repeated_dates.py +189 -41
  55. anemoi/datasets/create/input/result.py +202 -87
  56. anemoi/datasets/create/input/step.py +119 -22
  57. anemoi/datasets/create/input/template.py +100 -13
  58. anemoi/datasets/create/input/trace.py +62 -7
  59. anemoi/datasets/create/patch.py +52 -4
  60. anemoi/datasets/create/persistent.py +134 -17
  61. anemoi/datasets/create/size.py +15 -1
  62. anemoi/datasets/create/source.py +51 -0
  63. anemoi/datasets/create/sources/__init__.py +36 -0
  64. anemoi/datasets/create/{functions/sources → sources}/accumulations.py +296 -30
  65. anemoi/datasets/create/{functions/sources → sources}/constants.py +27 -2
  66. anemoi/datasets/create/{functions/sources → sources}/eccc_fstd.py +7 -3
  67. anemoi/datasets/create/sources/empty.py +37 -0
  68. anemoi/datasets/create/{functions/sources → sources}/forcings.py +25 -1
  69. anemoi/datasets/create/sources/grib.py +297 -0
  70. anemoi/datasets/create/{functions/sources → sources}/hindcasts.py +38 -4
  71. anemoi/datasets/create/sources/legacy.py +93 -0
  72. anemoi/datasets/create/{functions/sources → sources}/mars.py +168 -20
  73. anemoi/datasets/create/sources/netcdf.py +42 -0
  74. anemoi/datasets/create/sources/opendap.py +43 -0
  75. anemoi/datasets/create/{functions/sources/__init__.py → sources/patterns.py} +35 -4
  76. anemoi/datasets/create/sources/recentre.py +150 -0
  77. anemoi/datasets/create/{functions/sources → sources}/source.py +27 -5
  78. anemoi/datasets/create/{functions/sources → sources}/tendencies.py +64 -7
  79. anemoi/datasets/create/sources/xarray.py +92 -0
  80. anemoi/datasets/create/sources/xarray_kerchunk.py +36 -0
  81. anemoi/datasets/create/sources/xarray_support/README.md +1 -0
  82. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/__init__.py +109 -8
  83. anemoi/datasets/create/sources/xarray_support/coordinates.py +442 -0
  84. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/field.py +94 -16
  85. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/fieldlist.py +90 -25
  86. anemoi/datasets/create/sources/xarray_support/flavour.py +1036 -0
  87. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/grid.py +92 -31
  88. anemoi/datasets/create/sources/xarray_support/metadata.py +395 -0
  89. anemoi/datasets/create/sources/xarray_support/patch.py +91 -0
  90. anemoi/datasets/create/sources/xarray_support/time.py +391 -0
  91. anemoi/datasets/create/sources/xarray_support/variable.py +331 -0
  92. anemoi/datasets/create/sources/xarray_zarr.py +41 -0
  93. anemoi/datasets/create/{functions/sources → sources}/zenodo.py +34 -5
  94. anemoi/datasets/create/statistics/__init__.py +233 -44
  95. anemoi/datasets/create/statistics/summary.py +52 -6
  96. anemoi/datasets/create/testing.py +76 -0
  97. anemoi/datasets/create/{functions/filters/noop.py → typing.py} +6 -3
  98. anemoi/datasets/create/utils.py +97 -6
  99. anemoi/datasets/create/writer.py +26 -4
  100. anemoi/datasets/create/zarr.py +170 -23
  101. anemoi/datasets/data/__init__.py +51 -4
  102. anemoi/datasets/data/complement.py +191 -40
  103. anemoi/datasets/data/concat.py +141 -16
  104. anemoi/datasets/data/dataset.py +558 -62
  105. anemoi/datasets/data/debug.py +197 -26
  106. anemoi/datasets/data/ensemble.py +93 -8
  107. anemoi/datasets/data/fill_missing.py +165 -18
  108. anemoi/datasets/data/forwards.py +428 -56
  109. anemoi/datasets/data/grids.py +323 -97
  110. anemoi/datasets/data/indexing.py +112 -19
  111. anemoi/datasets/data/interpolate.py +92 -12
  112. anemoi/datasets/data/join.py +158 -19
  113. anemoi/datasets/data/masked.py +129 -15
  114. anemoi/datasets/data/merge.py +137 -23
  115. anemoi/datasets/data/misc.py +172 -16
  116. anemoi/datasets/data/missing.py +233 -29
  117. anemoi/datasets/data/rescale.py +111 -10
  118. anemoi/datasets/data/select.py +168 -26
  119. anemoi/datasets/data/statistics.py +67 -6
  120. anemoi/datasets/data/stores.py +149 -64
  121. anemoi/datasets/data/subset.py +159 -25
  122. anemoi/datasets/data/unchecked.py +168 -57
  123. anemoi/datasets/data/xy.py +168 -25
  124. anemoi/datasets/dates/__init__.py +191 -16
  125. anemoi/datasets/dates/groups.py +189 -47
  126. anemoi/datasets/grids.py +270 -31
  127. anemoi/datasets/testing.py +28 -1
  128. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/METADATA +9 -6
  129. anemoi_datasets-0.5.18.dist-info/RECORD +137 -0
  130. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/WHEEL +1 -1
  131. anemoi/datasets/create/functions/__init__.py +0 -66
  132. anemoi/datasets/create/functions/filters/__init__.py +0 -9
  133. anemoi/datasets/create/functions/filters/empty.py +0 -17
  134. anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
  135. anemoi/datasets/create/functions/filters/rename.py +0 -79
  136. anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
  137. anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
  138. anemoi/datasets/create/functions/sources/empty.py +0 -15
  139. anemoi/datasets/create/functions/sources/grib.py +0 -150
  140. anemoi/datasets/create/functions/sources/netcdf.py +0 -15
  141. anemoi/datasets/create/functions/sources/opendap.py +0 -15
  142. anemoi/datasets/create/functions/sources/recentre.py +0 -60
  143. anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
  144. anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
  145. anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
  146. anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
  147. anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
  148. anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
  149. anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
  150. anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
  151. anemoi/datasets/utils/fields.py +0 -47
  152. anemoi_datasets-0.5.16.dist-info/RECORD +0 -129
  153. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/entry_points.txt +0 -0
  154. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info/licenses}/LICENSE +0 -0
  155. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/top_level.txt +0 -0
@@ -10,9 +10,16 @@
10
10
  import logging
11
11
  from copy import deepcopy
12
12
  from functools import cached_property
13
+ from typing import Any
14
+ from typing import Dict
15
+ from typing import List
16
+ from typing import Union
17
+
18
+ from earthkit.data import FieldList
13
19
 
14
20
  from anemoi.datasets.dates import DatesProvider
15
21
 
22
+ from ...dates.groups import GroupOfDates
16
23
  from .action import Action
17
24
  from .action import action_factory
18
25
  from .empty import EmptyResult
@@ -27,7 +34,31 @@ LOG = logging.getLogger(__name__)
27
34
 
28
35
 
29
36
  class ConcatResult(Result):
30
- def __init__(self, context, action_path, group_of_dates, results, **kwargs):
37
+ """Represents the result of concatenating multiple results."""
38
+
39
+ def __init__(
40
+ self,
41
+ context: object,
42
+ action_path: List[str],
43
+ group_of_dates: GroupOfDates,
44
+ results: List[Result],
45
+ **kwargs: Any,
46
+ ) -> None:
47
+ """Initializes a ConcatResult instance.
48
+
49
+ Parameters
50
+ ----------
51
+ context : object
52
+ The context object.
53
+ action_path : List[str]
54
+ The action path.
55
+ group_of_dates : GroupOfDates
56
+ The group of dates.
57
+ results : List[Result]
58
+ The list of results.
59
+ kwargs : Any
60
+ Additional keyword arguments.
61
+ """
31
62
  super().__init__(context, action_path, group_of_dates)
32
63
  self.results = [r for r in results if not r.empty]
33
64
 
@@ -35,15 +66,16 @@ class ConcatResult(Result):
35
66
  @assert_fieldlist
36
67
  @notify_result
37
68
  @trace_datasource
38
- def datasource(self):
69
+ def datasource(self) -> FieldList:
70
+ """Returns the concatenated datasource from all results."""
39
71
  ds = EmptyResult(self.context, self.action_path, self.group_of_dates).datasource
40
72
  for i in self.results:
41
73
  ds += i.datasource
42
74
  return _tidy(ds)
43
75
 
44
76
  @property
45
- def variables(self):
46
- """Check that all the results objects have the same variables."""
77
+ def variables(self) -> List[str]:
78
+ """Returns the list of variables, ensuring all results have the same variables."""
47
79
  variables = None
48
80
  for f in self.results:
49
81
  if f.empty:
@@ -54,13 +86,33 @@ class ConcatResult(Result):
54
86
  assert variables is not None, self.results
55
87
  return variables
56
88
 
57
- def __repr__(self):
89
+ def __repr__(self) -> str:
90
+ """Returns a string representation of the ConcatResult instance.
91
+
92
+ Returns
93
+ -------
94
+ str
95
+ A string representation of the ConcatResult instance.
96
+ """
58
97
  content = "\n".join([str(i) for i in self.results])
59
- return super().__repr__(content)
98
+ return self._repr(content)
60
99
 
61
100
 
62
101
  class ConcatAction(Action):
63
- def __init__(self, context, action_path, *configs):
102
+ """Represents an action that concatenates multiple actions based on their dates."""
103
+
104
+ def __init__(self, context: object, action_path: List[str], *configs: Dict[str, Any]) -> None:
105
+ """Initializes a ConcatAction instance.
106
+
107
+ Parameters
108
+ ----------
109
+ context : object
110
+ The context object.
111
+ action_path : List[str]
112
+ The action path.
113
+ configs : Dict[str, Any]
114
+ The configuration dictionaries.
115
+ """
64
116
  super().__init__(context, action_path, *configs)
65
117
  parts = []
66
118
  for i, cfg in enumerate(configs):
@@ -74,12 +126,31 @@ class ConcatAction(Action):
74
126
  parts.append((filtering_dates, action))
75
127
  self.parts = parts
76
128
 
77
- def __repr__(self):
129
+ def __repr__(self) -> str:
130
+ """Returns a string representation of the ConcatAction instance.
131
+
132
+ Returns
133
+ -------
134
+ str
135
+ A string representation of the ConcatAction instance.
136
+ """
78
137
  content = "\n".join([str(i) for i in self.parts])
79
- return super().__repr__(content)
138
+ return self._repr(content)
80
139
 
81
140
  @trace_select
82
- def select(self, group_of_dates):
141
+ def select(self, group_of_dates: GroupOfDates) -> Union[ConcatResult, EmptyResult]:
142
+ """Selects the concatenated result for the given group of dates.
143
+
144
+ Parameters
145
+ ----------
146
+ group_of_dates : GroupOfDates
147
+ The group of dates.
148
+
149
+ Returns
150
+ -------
151
+ Union[ConcatResult, EmptyResult]
152
+ The concatenated result or an empty result.
153
+ """
83
154
  from anemoi.datasets.dates.groups import GroupOfDates
84
155
 
85
156
  results = []
@@ -9,6 +9,10 @@
9
9
 
10
10
  import logging
11
11
  import textwrap
12
+ from typing import Any
13
+ from typing import List
14
+ from typing import Tuple
15
+ from typing import Union
12
16
 
13
17
  from anemoi.utils.humanize import plural
14
18
 
@@ -19,18 +23,37 @@ LOG = logging.getLogger(__name__)
19
23
 
20
24
 
21
25
  class Context:
22
- def __init__(self):
26
+ """Class to handle the build context in the dataset creation process."""
27
+
28
+ def __init__(self) -> None:
29
+ """Initializes a Context instance."""
23
30
  # used_references is a set of reference paths that will be needed
24
31
  self.used_references = set()
25
32
  # results is a dictionary of reference path -> obj
26
33
  self.results = {}
27
34
 
28
- def will_need_reference(self, key):
35
+ def will_need_reference(self, key: Union[List, Tuple]) -> None:
36
+ """Marks a reference as needed.
37
+
38
+ Parameters
39
+ ----------
40
+ key : Union[List, Tuple]
41
+ The reference key.
42
+ """
29
43
  assert isinstance(key, (list, tuple)), key
30
44
  key = tuple(key)
31
45
  self.used_references.add(key)
32
46
 
33
- def notify_result(self, key, result):
47
+ def notify_result(self, key: Union[List, Tuple], result: Any) -> None:
48
+ """Notifies that a result is available for a reference.
49
+
50
+ Parameters
51
+ ----------
52
+ key : Union[List, Tuple]
53
+ The reference key.
54
+ result : Any
55
+ The result object.
56
+ """
34
57
  trace(
35
58
  "🎯",
36
59
  step(key),
@@ -45,7 +68,19 @@ class Context:
45
68
  raise ValueError(f"Duplicate result {key}")
46
69
  self.results[key] = result
47
70
 
48
- def get_result(self, key):
71
+ def get_result(self, key: Union[List, Tuple]) -> Any:
72
+ """Retrieves the result for a given reference.
73
+
74
+ Parameters
75
+ ----------
76
+ key : Union[List, Tuple]
77
+ The reference key.
78
+
79
+ Returns
80
+ -------
81
+ Any
82
+ The result for the given reference.
83
+ """
49
84
  assert isinstance(key, (list, tuple)), key
50
85
  key = tuple(key)
51
86
  if key in self.results:
@@ -9,7 +9,14 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
+ from typing import Any
13
+ from typing import Dict
14
+ from typing import List
15
+ from typing import Union
12
16
 
17
+ from earthkit.data import FieldList
18
+
19
+ from ...dates.groups import GroupOfDates
13
20
  from .action import Action
14
21
  from .action import action_factory
15
22
  from .misc import _tidy
@@ -19,7 +26,28 @@ LOG = logging.getLogger(__name__)
19
26
 
20
27
 
21
28
  class DataSourcesAction(Action):
22
- def __init__(self, context, action_path, sources, input):
29
+ """Class to handle data sources actions in the dataset creation process."""
30
+
31
+ def __init__(
32
+ self,
33
+ context: object,
34
+ action_path: List[str],
35
+ sources: Union[Dict[str, Any], List[Dict[str, Any]]],
36
+ input: Dict[str, Any],
37
+ ) -> None:
38
+ """Initializes a DataSourcesAction instance.
39
+
40
+ Parameters
41
+ ----------
42
+ context : object
43
+ The context object.
44
+ action_path : List[str]
45
+ The action path.
46
+ sources : Union[Dict[str, Any], List[Dict[str, Any]]]
47
+ The sources configuration.
48
+ input : Dict[str, Any]
49
+ The input configuration.
50
+ """
23
51
  super().__init__(context, ["data_sources"], *sources)
24
52
  if isinstance(sources, dict):
25
53
  configs = [(str(k), c) for k, c in sources.items()]
@@ -31,7 +59,19 @@ class DataSourcesAction(Action):
31
59
  self.sources = [action_factory(config, context, ["data_sources"] + [a_path]) for a_path, config in configs]
32
60
  self.input = action_factory(input, context, ["input"])
33
61
 
34
- def select(self, group_of_dates):
62
+ def select(self, group_of_dates: GroupOfDates) -> "DataSourcesResult":
63
+ """Selects the data sources result for the given group of dates.
64
+
65
+ Parameters
66
+ ----------
67
+ group_of_dates : GroupOfDates
68
+ The group of dates.
69
+
70
+ Returns
71
+ -------
72
+ DataSourcesResult
73
+ The data sources result.
74
+ """
35
75
  sources_results = [a.select(group_of_dates) for a in self.sources]
36
76
  return DataSourcesResult(
37
77
  self.context,
@@ -41,13 +81,38 @@ class DataSourcesAction(Action):
41
81
  sources_results,
42
82
  )
43
83
 
44
- def __repr__(self):
84
+ def __repr__(self) -> str:
85
+ """Returns a string representation of the DataSourcesAction instance."""
45
86
  content = "\n".join([str(i) for i in self.sources])
46
- return super().__repr__(content)
87
+ return self._repr(content)
47
88
 
48
89
 
49
90
  class DataSourcesResult(Result):
50
- def __init__(self, context, action_path, dates, input_result, sources_results):
91
+ """Class to represent the result of data sources actions in the dataset creation process."""
92
+
93
+ def __init__(
94
+ self,
95
+ context: object,
96
+ action_path: List[str],
97
+ dates: object,
98
+ input_result: Result,
99
+ sources_results: List[Result],
100
+ ) -> None:
101
+ """Initializes a DataSourcesResult instance.
102
+
103
+ Parameters
104
+ ----------
105
+ context : object
106
+ The context object.
107
+ action_path : List[str]
108
+ The action path.
109
+ dates : object
110
+ The dates object.
111
+ input_result : Result
112
+ The input result.
113
+ sources_results : List[Result]
114
+ The list of sources results.
115
+ """
51
116
  super().__init__(context, action_path, dates)
52
117
  # result is the main input result
53
118
  self.input_result = input_result
@@ -55,7 +120,8 @@ class DataSourcesResult(Result):
55
120
  self.sources_results = sources_results
56
121
 
57
122
  @cached_property
58
- def datasource(self):
123
+ def datasource(self) -> FieldList:
124
+ """Returns the combined datasource from all sources."""
59
125
  for i in self.sources_results:
60
126
  # for each result trigger the datasource to be computed
61
127
  # and saved in context
@@ -9,6 +9,9 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
+ from typing import List
13
+
14
+ from earthkit.data import FieldList
12
15
 
13
16
  from .misc import assert_fieldlist
14
17
  from .result import Result
@@ -18,19 +21,34 @@ LOG = logging.getLogger(__name__)
18
21
 
19
22
 
20
23
  class EmptyResult(Result):
24
+ """Class to represent an empty result in the dataset creation process."""
25
+
21
26
  empty = True
22
27
 
23
- def __init__(self, context, action_path, dates):
28
+ def __init__(self, context: object, action_path: list, dates: object) -> None:
29
+ """Initializes an EmptyResult instance.
30
+
31
+ Parameters
32
+ ----------
33
+ context : object
34
+ The context object.
35
+ action_path : list
36
+ The action path.
37
+ dates : object
38
+ The dates object.
39
+ """
24
40
  super().__init__(context, action_path + ["empty"], dates)
25
41
 
26
42
  @cached_property
27
43
  @assert_fieldlist
28
44
  @trace_datasource
29
- def datasource(self):
45
+ def datasource(self) -> FieldList:
46
+ """Returns an empty datasource."""
30
47
  from earthkit.data import from_source
31
48
 
32
49
  return from_source("empty")
33
50
 
34
51
  @property
35
- def variables(self):
52
+ def variables(self) -> List[str]:
53
+ """Returns an empty list of variables."""
36
54
  return []
@@ -9,8 +9,11 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
+ from typing import Any
13
+ from typing import Type
14
+
15
+ from earthkit.data import FieldList
12
16
 
13
- from ..functions import import_function
14
17
  from .function import FunctionContext
15
18
  from .misc import _tidy
16
19
  from .misc import assert_fieldlist
@@ -27,14 +30,17 @@ class FilterStepResult(StepResult):
27
30
  @notify_result
28
31
  @assert_fieldlist
29
32
  @trace_datasource
30
- def datasource(self):
31
- ds = self.upstream_result.datasource
33
+ def datasource(self) -> FieldList:
34
+ """Returns the filtered datasource."""
35
+ ds: FieldList = self.upstream_result.datasource
32
36
  ds = ds.sel(**self.action.kwargs)
33
37
  return _tidy(ds)
34
38
 
35
39
 
36
40
  class FilterStepAction(StepAction):
37
- result_class = FilterStepResult
41
+ """Represents an action to filter a step result."""
42
+
43
+ result_class: Type[FilterStepResult] = FilterStepResult
38
44
 
39
45
 
40
46
  class StepFunctionResult(StepResult):
@@ -42,11 +48,13 @@ class StepFunctionResult(StepResult):
42
48
  @assert_fieldlist
43
49
  @notify_result
44
50
  @trace_datasource
45
- def datasource(self):
51
+ def datasource(self) -> FieldList:
52
+ """Returns the datasource after applying the function."""
53
+
54
+ self.action.filter.context = FunctionContext(self)
46
55
  try:
47
56
  return _tidy(
48
- self.action.function(
49
- FunctionContext(self),
57
+ self.action.filter.execute(
50
58
  self.upstream_result.datasource,
51
59
  *self.action.args[1:],
52
60
  **self.action.kwargs,
@@ -57,14 +65,54 @@ class StepFunctionResult(StepResult):
57
65
  LOG.error(f"Error in {self.action.name}", exc_info=True)
58
66
  raise
59
67
 
60
- def _trace_datasource(self, *args, **kwargs):
68
+ def _trace_datasource(self, *args: Any, **kwargs: Any) -> str:
69
+ """Traces the datasource for the given arguments.
70
+
71
+ Parameters
72
+ ----------
73
+ *args : Any
74
+ The arguments.
75
+ **kwargs : Any
76
+ The keyword arguments.
77
+
78
+ Returns
79
+ -------
80
+ str
81
+ A string representation of the traced datasource.
82
+ """
61
83
  return f"{self.action.name}({self.group_of_dates})"
62
84
 
63
85
 
64
86
  class FunctionStepAction(StepAction):
65
- result_class = StepFunctionResult
87
+ """Represents an action to apply a function to a step result."""
88
+
89
+ result_class: Type[StepFunctionResult] = StepFunctionResult
90
+
91
+ def __init__(
92
+ self,
93
+ context: object,
94
+ action_path: list,
95
+ previous_step: StepAction,
96
+ name: str,
97
+ filter: Any,
98
+ *args: Any,
99
+ **kwargs: Any,
100
+ ) -> None:
101
+ """Initializes a FunctionStepAction instance.
66
102
 
67
- def __init__(self, context, action_path, previous_step, *args, **kwargs):
103
+ Parameters
104
+ ----------
105
+ context : object
106
+ The context object.
107
+ action_path : list
108
+ The action path.
109
+ previous_step : StepAction
110
+ The previous step action.
111
+ *args : Any
112
+ Additional arguments.
113
+ **kwargs : Any
114
+ Additional keyword arguments.
115
+ """
68
116
  super().__init__(context, action_path, previous_step, *args, **kwargs)
69
- self.name = args[0]
70
- self.function = import_function(self.name, "filters")
117
+ self.name = name
118
+ self.filter = filter