anemoi-datasets 0.5.15__py3-none-any.whl → 0.5.17__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 +552 -61
  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.15.dist-info → anemoi_datasets-0.5.17.dist-info}/METADATA +10 -7
  129. anemoi_datasets-0.5.17.dist-info/RECORD +137 -0
  130. {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/WHEEL +1 -1
  131. {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info/licenses}/LICENSE +1 -1
  132. anemoi/datasets/create/functions/__init__.py +0 -66
  133. anemoi/datasets/create/functions/filters/__init__.py +0 -9
  134. anemoi/datasets/create/functions/filters/empty.py +0 -17
  135. anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
  136. anemoi/datasets/create/functions/filters/rename.py +0 -79
  137. anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
  138. anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
  139. anemoi/datasets/create/functions/sources/empty.py +0 -15
  140. anemoi/datasets/create/functions/sources/grib.py +0 -150
  141. anemoi/datasets/create/functions/sources/netcdf.py +0 -15
  142. anemoi/datasets/create/functions/sources/opendap.py +0 -15
  143. anemoi/datasets/create/functions/sources/recentre.py +0 -60
  144. anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
  145. anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
  146. anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
  147. anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
  148. anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
  149. anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
  150. anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
  151. anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
  152. anemoi/datasets/utils/fields.py +0 -47
  153. anemoi_datasets-0.5.15.dist-info/RECORD +0 -129
  154. {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/entry_points.txt +0 -0
  155. {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/top_level.txt +0 -0
@@ -9,8 +9,12 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
+ from typing import Any
13
+ from typing import Dict
12
14
 
13
- from ..functions import import_function
15
+ from earthkit.data import FieldList
16
+
17
+ from ...dates.groups import GroupOfDates
14
18
  from .action import Action
15
19
  from .misc import _tidy
16
20
  from .misc import assert_fieldlist
@@ -30,87 +34,200 @@ class FunctionContext:
30
34
  to the functions from the other actions and filters and results.
31
35
  """
32
36
 
33
- def __init__(self, owner):
34
- self.owner = owner
35
- self.use_grib_paramid = owner.context.use_grib_paramid
37
+ def __init__(self, owner: Result) -> None:
38
+ """Initializes a FunctionContext instance.
36
39
 
37
- def trace(self, emoji, *args):
40
+ Parameters
41
+ ----------
42
+ owner : object
43
+ The owner object.
44
+ """
45
+ self.owner = owner
46
+ self.use_grib_paramid: bool = owner.context.use_grib_paramid
47
+
48
+ def trace(self, emoji: str, *args: Any) -> None:
49
+ """Traces the given arguments with an emoji.
50
+
51
+ Parameters
52
+ ----------
53
+ emoji : str
54
+ The emoji to use.
55
+ *args : Any
56
+ The arguments to trace.
57
+ """
38
58
  trace(emoji, *args)
39
59
 
40
- def info(self, *args, **kwargs):
60
+ def info(self, *args: Any, **kwargs: Any) -> None:
61
+ """Logs an info message.
62
+
63
+ Parameters
64
+ ----------
65
+ *args : Any
66
+ The arguments for the log message.
67
+ **kwargs : Any
68
+ The keyword arguments for the log message.
69
+ """
41
70
  LOG.info(*args, **kwargs)
42
71
 
43
72
  @property
44
- def dates_provider(self):
73
+ def dates_provider(self) -> object:
74
+ """Returns the dates provider."""
45
75
  return self.owner.group_of_dates.provider
46
76
 
47
77
  @property
48
- def partial_ok(self):
78
+ def partial_ok(self) -> bool:
79
+ """Returns whether partial results are acceptable."""
49
80
  return self.owner.group_of_dates.partial_ok
50
81
 
51
82
 
52
83
  class FunctionAction(Action):
53
- def __init__(self, context, action_path, _name, **kwargs):
84
+ """Represents an action that executes a function.
85
+
86
+ Attributes
87
+ ----------
88
+ name : str
89
+ The name of the function.
90
+ """
91
+
92
+ def __init__(self, context: object, action_path: list, _name: str, source, **kwargs: Dict[str, Any]) -> None:
93
+ """Initializes a FunctionAction instance.
94
+
95
+ Parameters
96
+ ----------
97
+ context : object
98
+ The context object.
99
+ action_path : list
100
+ The action path.
101
+ _name : str
102
+ The name of the function.
103
+ **kwargs : Dict[str, Any]
104
+ Additional keyword arguments.
105
+ """
54
106
  super().__init__(context, action_path, **kwargs)
55
- self.name = _name
107
+ self.name: str = _name
108
+ self.source = source
56
109
 
57
110
  @trace_select
58
- def select(self, group_of_dates):
111
+ def select(self, group_of_dates: GroupOfDates) -> "FunctionResult":
112
+ """Selects the function result for the given group of dates.
113
+
114
+ Parameters
115
+ ----------
116
+ group_of_dates : GroupOfDates
117
+ The group of dates.
118
+
119
+ Returns
120
+ -------
121
+ FunctionResult
122
+ The function result instance.
123
+ """
59
124
  return FunctionResult(self.context, self.action_path, group_of_dates, action=self)
60
125
 
61
- @property
62
- def function(self):
63
- # name, delta = parse_function_name(self.name)
64
- return import_function(self.name, "sources")
65
-
66
- def __repr__(self):
67
- content = ""
126
+ def __repr__(self) -> str:
127
+ """Returns a string representation of the FunctionAction instance."""
128
+ content: str = ""
68
129
  content += ",".join([self._short_str(a) for a in self.args])
69
130
  content += " ".join([self._short_str(f"{k}={v}") for k, v in self.kwargs.items()])
70
131
  content = self._short_str(content)
71
- return super().__repr__(_inline_=content, _indent_=" ")
132
+ return self._repr(_inline_=content, _indent_=" ")
133
+
134
+ def _trace_select(self, group_of_dates: GroupOfDates) -> str:
135
+ """Traces the selection of the function for the given group of dates.
72
136
 
73
- def _trace_select(self, group_of_dates):
137
+ Parameters
138
+ ----------
139
+ group_of_dates : GroupOfDates
140
+ The group of dates.
141
+
142
+ Returns
143
+ -------
144
+ str
145
+ The trace string.
146
+ """
74
147
  return f"{self.name}({group_of_dates})"
75
148
 
76
149
 
77
150
  class FunctionResult(Result):
78
- def __init__(self, context, action_path, group_of_dates, action):
151
+ """Represents the result of executing a function.
152
+
153
+ Attributes
154
+ ----------
155
+ action : Action
156
+ The action instance.
157
+ args : tuple
158
+ The positional arguments for the function.
159
+ kwargs : dict
160
+ The keyword arguments for the function.
161
+ """
162
+
163
+ def __init__(self, context: object, action_path: list, group_of_dates: GroupOfDates, action: Action) -> None:
164
+ """Initializes a FunctionResult instance.
165
+
166
+ Parameters
167
+ ----------
168
+ context : object
169
+ The context object.
170
+ action_path : list
171
+ The action path.
172
+ group_of_dates : GroupOfDates
173
+ The group of dates.
174
+ action : Action
175
+ The action instance.
176
+ """
79
177
  super().__init__(context, action_path, group_of_dates)
80
178
  assert isinstance(action, Action), type(action)
81
- self.action = action
179
+ self.action: Action = action
82
180
 
83
181
  self.args, self.kwargs = substitute(context, (self.action.args, self.action.kwargs))
84
182
 
85
- def _trace_datasource(self, *args, **kwargs):
183
+ def _trace_datasource(self, *args: Any, **kwargs: Any) -> str:
184
+ """Traces the datasource for the given arguments.
185
+
186
+ Parameters
187
+ ----------
188
+ *args : Any
189
+ The arguments.
190
+ **kwargs : Any
191
+ The keyword arguments.
192
+
193
+ Returns
194
+ -------
195
+ str
196
+ The trace string.
197
+ """
86
198
  return f"{self.action.name}({self.group_of_dates})"
87
199
 
88
200
  @cached_property
89
201
  @assert_fieldlist
90
202
  @notify_result
91
203
  @trace_datasource
92
- def datasource(self):
204
+ def datasource(self) -> FieldList:
205
+ """Returns the datasource for the function result."""
93
206
  args, kwargs = resolve(self.context, (self.args, self.kwargs))
207
+ self.action.source.context = FunctionContext(self)
94
208
 
95
- try:
96
- return _tidy(
97
- self.action.function(
98
- FunctionContext(self),
99
- list(self.group_of_dates), # Will provide a list of datetime objects
100
- *args,
101
- **kwargs,
102
- )
209
+ return _tidy(
210
+ self.action.source.execute(
211
+ self.group_of_dates, # Will provide a list of datetime objects
212
+ *args,
213
+ **kwargs,
103
214
  )
104
- except Exception:
105
- LOG.error(f"Error in {self.action.function.__name__}", exc_info=True)
106
- raise
215
+ )
107
216
 
108
- def __repr__(self):
217
+ def __repr__(self) -> str:
218
+ """Returns a string representation of the FunctionResult instance."""
109
219
  try:
110
220
  return f"{self.action.name}({self.group_of_dates})"
111
221
  except Exception:
112
222
  return f"{self.__class__.__name__}(unitialised)"
113
223
 
114
224
  @property
115
- def function(self):
225
+ def function(self) -> None:
226
+ """Raises NotImplementedError as this property is not implemented.
227
+
228
+ Raises
229
+ ------
230
+ NotImplementedError
231
+ Always raised.
232
+ """
116
233
  raise NotImplementedError(f"Not implemented in {self.__class__.__name__}")
@@ -9,7 +9,12 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
+ from typing import Any
13
+ from typing import List
12
14
 
15
+ from earthkit.data import FieldList
16
+
17
+ from ...dates.groups import GroupOfDates
13
18
  from .action import Action
14
19
  from .action import action_factory
15
20
  from .empty import EmptyResult
@@ -24,35 +29,102 @@ LOG = logging.getLogger(__name__)
24
29
 
25
30
 
26
31
  class JoinResult(Result):
27
- def __init__(self, context, action_path, group_of_dates, results, **kwargs):
32
+ """Represents a result that combines multiple results.
33
+
34
+ Attributes
35
+ ----------
36
+ context : object
37
+ The context object.
38
+ action_path : list
39
+ The action path.
40
+ group_of_dates : GroupOfDates
41
+ The group of dates.
42
+ results : List[Result]
43
+ The list of results.
44
+ """
45
+
46
+ def __init__(
47
+ self, context: object, action_path: list, group_of_dates: GroupOfDates, results: List[Result], **kwargs: Any
48
+ ) -> None:
49
+ """Initializes a JoinResult instance.
50
+
51
+ Parameters
52
+ ----------
53
+ context : object
54
+ The context object.
55
+ action_path : list
56
+ The action path.
57
+ group_of_dates : GroupOfDates
58
+ The group of dates.
59
+ results : List[Result]
60
+ The list of results.
61
+ """
28
62
  super().__init__(context, action_path, group_of_dates)
29
- self.results = [r for r in results if not r.empty]
63
+ self.results: List[Result] = [r for r in results if not r.empty]
30
64
 
31
65
  @cached_property
32
66
  @assert_fieldlist
33
67
  @notify_result
34
68
  @trace_datasource
35
- def datasource(self):
36
- ds = EmptyResult(self.context, self.action_path, self.group_of_dates).datasource
69
+ def datasource(self) -> FieldList:
70
+ """Returns the combined datasource from all results."""
71
+ ds: FieldList = EmptyResult(self.context, self.action_path, self.group_of_dates).datasource
37
72
  for i in self.results:
38
73
  ds += i.datasource
39
74
  return _tidy(ds)
40
75
 
41
- def __repr__(self):
42
- content = "\n".join([str(i) for i in self.results])
43
- return super().__repr__(content)
76
+ def __repr__(self) -> str:
77
+ """Returns a string representation of the JoinResult instance."""
78
+ content: str = "\n".join([str(i) for i in self.results])
79
+ return self._repr(content)
44
80
 
45
81
 
46
82
  class JoinAction(Action):
47
- def __init__(self, context, action_path, *configs):
83
+ """Represents an action that combines multiple actions.
84
+
85
+ Attributes
86
+ ----------
87
+ context : object
88
+ The context object.
89
+ action_path : list
90
+ The action path.
91
+ actions : List[Action]
92
+ The list of actions.
93
+ """
94
+
95
+ def __init__(self, context: object, action_path: list, *configs: dict) -> None:
96
+ """Initializes a JoinAction instance.
97
+
98
+ Parameters
99
+ ----------
100
+ context : object
101
+ The context object.
102
+ action_path : list
103
+ The action path.
104
+ *configs : dict
105
+ The configuration dictionaries.
106
+ """
48
107
  super().__init__(context, action_path, *configs)
49
- self.actions = [action_factory(c, context, action_path + [str(i)]) for i, c in enumerate(configs)]
108
+ self.actions: List[Action] = [action_factory(c, context, action_path + [str(i)]) for i, c in enumerate(configs)]
50
109
 
51
- def __repr__(self):
52
- content = "\n".join([str(i) for i in self.actions])
53
- return super().__repr__(content)
110
+ def __repr__(self) -> str:
111
+ """Returns a string representation of the JoinAction instance."""
112
+ content: str = "\n".join([str(i) for i in self.actions])
113
+ return self._repr(content)
54
114
 
55
115
  @trace_select
56
- def select(self, group_of_dates):
57
- results = [a.select(group_of_dates) for a in self.actions]
116
+ def select(self, group_of_dates: GroupOfDates) -> JoinResult:
117
+ """Selects the results for the given group of dates.
118
+
119
+ Parameters
120
+ ----------
121
+ group_of_dates : GroupOfDates
122
+ The group of dates.
123
+
124
+ Returns
125
+ -------
126
+ JoinResult
127
+ The combined result for the given group of dates.
128
+ """
129
+ results: List[Result] = [a.select(group_of_dates) for a in self.actions]
58
130
  return JoinResult(self.context, self.action_path, group_of_dates, results)
@@ -9,17 +9,30 @@
9
9
 
10
10
  import logging
11
11
  from functools import wraps
12
+ from typing import Any
13
+ from typing import Callable
14
+ from typing import Tuple
15
+ from typing import Union
12
16
 
17
+ from earthkit.data import FieldList
13
18
  from earthkit.data.core.fieldlist import MultiFieldList
14
- from earthkit.data.indexing.fieldlist import FieldList
15
-
16
- from ..functions import import_function
17
19
 
18
20
  LOG = logging.getLogger(__name__)
19
21
 
20
22
 
21
- def parse_function_name(name):
23
+ def parse_function_name(name: str) -> Tuple[str, Union[int, None]]:
24
+ """Parses a function name to extract the base name and an optional time delta.
25
+
26
+ Parameters
27
+ ----------
28
+ name : str
29
+ The function name to parse.
22
30
 
31
+ Returns
32
+ -------
33
+ tuple of (str, int or None)
34
+ The base name and an optional time delta.
35
+ """
23
36
  if name.endswith("h") and name[:-1].isdigit():
24
37
 
25
38
  if "-" in name:
@@ -40,19 +53,23 @@ def parse_function_name(name):
40
53
  return name, None
41
54
 
42
55
 
43
- def is_function(name, kind):
44
- name, _ = parse_function_name(name)
45
- try:
46
- import_function(name, kind)
47
- return True
48
- except ImportError as e:
49
- print(e)
50
- return False
56
+ def assert_fieldlist(method: Callable[..., Any]) -> Callable[..., Any]:
57
+ """Decorator to assert that the result of a method is an instance of FieldList.
58
+
59
+ Parameters
60
+ ----------
61
+ method : Callable[..., Any]
62
+ The method to decorate.
51
63
 
64
+ Returns
65
+ -------
66
+ Callable[..., Any]
67
+ The decorated method.
68
+ """
52
69
 
53
- def assert_fieldlist(method):
54
70
  @wraps(method)
55
- def wrapper(self, *args, **kwargs):
71
+ def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
72
+
56
73
  result = method(self, *args, **kwargs)
57
74
  assert isinstance(result, FieldList), type(result)
58
75
  return result
@@ -60,17 +77,50 @@ def assert_fieldlist(method):
60
77
  return wrapper
61
78
 
62
79
 
63
- def assert_is_fieldlist(obj):
80
+ def assert_is_fieldlist(obj: object) -> None:
81
+ """Asserts that the given object is an instance of FieldList.
82
+
83
+ Parameters
84
+ ----------
85
+ obj : object
86
+ The object to check.
87
+ """
64
88
  assert isinstance(obj, FieldList), type(obj)
65
89
 
66
90
 
67
- def _flatten(ds):
91
+ def _flatten(ds: Union[MultiFieldList, FieldList]) -> list:
92
+ """Flattens a MultiFieldList or FieldList into a list of FieldList objects.
93
+
94
+ Parameters
95
+ ----------
96
+ ds : Union[MultiFieldList, FieldList]
97
+ The dataset to flatten.
98
+
99
+ Returns
100
+ -------
101
+ list
102
+ A list of FieldList objects.
103
+ """
68
104
  if isinstance(ds, MultiFieldList):
69
105
  return [_tidy(f) for s in ds._indexes for f in _flatten(s)]
70
106
  return [ds]
71
107
 
72
108
 
73
- def _tidy(ds, indent=0):
109
+ def _tidy(ds: Union[MultiFieldList, FieldList], indent: int = 0) -> Union[MultiFieldList, FieldList]:
110
+ """Tidies up a MultiFieldList or FieldList by removing empty sources.
111
+
112
+ Parameters
113
+ ----------
114
+ ds : Union[MultiFieldList, FieldList]
115
+ The dataset to tidy.
116
+ indent : int, optional
117
+ The indentation level. Defaults to 0.
118
+
119
+ Returns
120
+ -------
121
+ Union[MultiFieldList, FieldList]
122
+ The tidied dataset.
123
+ """
74
124
  if isinstance(ds, MultiFieldList):
75
125
 
76
126
  sources = [s for s in _flatten(ds) if len(s) > 0]
@@ -9,6 +9,7 @@
9
9
 
10
10
  import json
11
11
  import logging
12
+ from typing import Any
12
13
 
13
14
  from .action import Action
14
15
  from .action import action_factory
@@ -19,21 +20,47 @@ LOG = logging.getLogger(__name__)
19
20
 
20
21
 
21
22
  class PipeAction(Action):
22
- def __init__(self, context, action_path, *configs):
23
+ """A class to represent a pipeline of actions."""
24
+
25
+ def __init__(self, context: Any, action_path: list, *configs: dict) -> None:
26
+ """Initialize the PipeAction.
27
+
28
+ Parameters
29
+ ----------
30
+ context : Any
31
+ The context for the action.
32
+ action_path : list
33
+ The path of the action.
34
+ configs : dict
35
+ The configurations for the actions.
36
+ """
23
37
  super().__init__(context, action_path, *configs)
24
38
  if len(configs) <= 1:
25
39
  raise ValueError(
26
40
  f"PipeAction requires at least two actions, got {len(configs)}\n{json.dumps(configs, indent=2)}"
27
41
  )
28
42
 
29
- current = action_factory(configs[0], context, action_path + ["0"])
43
+ current: Any = action_factory(configs[0], context, action_path + ["0"])
30
44
  for i, c in enumerate(configs[1:]):
31
45
  current = step_factory(c, context, action_path + [str(i + 1)], previous_step=current)
32
- self.last_step = current
46
+ self.last_step: Any = current
33
47
 
34
48
  @trace_select
35
- def select(self, group_of_dates):
49
+ def select(self, group_of_dates: Any) -> Any:
50
+ """Select data based on the group of dates.
51
+
52
+ Parameters
53
+ ----------
54
+ group_of_dates : Any
55
+ The group of dates to select data for.
56
+
57
+ Returns
58
+ -------
59
+ Any
60
+ The selected data.
61
+ """
36
62
  return self.last_step.select(group_of_dates)
37
63
 
38
- def __repr__(self):
39
- return super().__repr__(self.last_step)
64
+ def __repr__(self) -> str:
65
+ """Return a string representation of the PipeAction."""
66
+ return f"PipeAction({self.last_step})"