anemoi-datasets 0.5.26__py3-none-any.whl → 0.5.27__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 (105) hide show
  1. anemoi/datasets/__init__.py +1 -2
  2. anemoi/datasets/_version.py +16 -3
  3. anemoi/datasets/commands/check.py +1 -1
  4. anemoi/datasets/commands/copy.py +1 -2
  5. anemoi/datasets/commands/create.py +1 -1
  6. anemoi/datasets/commands/inspect.py +27 -35
  7. anemoi/datasets/commands/validate.py +59 -0
  8. anemoi/datasets/compute/recentre.py +3 -6
  9. anemoi/datasets/create/__init__.py +22 -25
  10. anemoi/datasets/create/check.py +10 -12
  11. anemoi/datasets/create/chunks.py +1 -2
  12. anemoi/datasets/create/config.py +3 -6
  13. anemoi/datasets/create/filter.py +1 -2
  14. anemoi/datasets/create/input/__init__.py +1 -2
  15. anemoi/datasets/create/input/action.py +3 -5
  16. anemoi/datasets/create/input/concat.py +5 -8
  17. anemoi/datasets/create/input/context.py +3 -6
  18. anemoi/datasets/create/input/data_sources.py +5 -8
  19. anemoi/datasets/create/input/empty.py +1 -2
  20. anemoi/datasets/create/input/filter.py +2 -3
  21. anemoi/datasets/create/input/function.py +1 -2
  22. anemoi/datasets/create/input/join.py +4 -5
  23. anemoi/datasets/create/input/misc.py +4 -6
  24. anemoi/datasets/create/input/repeated_dates.py +13 -18
  25. anemoi/datasets/create/input/result.py +29 -33
  26. anemoi/datasets/create/input/step.py +4 -8
  27. anemoi/datasets/create/input/template.py +3 -4
  28. anemoi/datasets/create/input/trace.py +1 -1
  29. anemoi/datasets/create/patch.py +1 -2
  30. anemoi/datasets/create/persistent.py +3 -5
  31. anemoi/datasets/create/size.py +1 -3
  32. anemoi/datasets/create/sources/accumulations.py +47 -52
  33. anemoi/datasets/create/sources/accumulations2.py +4 -8
  34. anemoi/datasets/create/sources/constants.py +1 -3
  35. anemoi/datasets/create/sources/empty.py +1 -2
  36. anemoi/datasets/create/sources/fdb.py +133 -0
  37. anemoi/datasets/create/sources/forcings.py +1 -2
  38. anemoi/datasets/create/sources/grib.py +6 -10
  39. anemoi/datasets/create/sources/grib_index.py +13 -15
  40. anemoi/datasets/create/sources/hindcasts.py +2 -5
  41. anemoi/datasets/create/sources/legacy.py +1 -1
  42. anemoi/datasets/create/sources/mars.py +17 -21
  43. anemoi/datasets/create/sources/netcdf.py +1 -2
  44. anemoi/datasets/create/sources/opendap.py +1 -3
  45. anemoi/datasets/create/sources/patterns.py +4 -6
  46. anemoi/datasets/create/sources/recentre.py +8 -11
  47. anemoi/datasets/create/sources/source.py +3 -6
  48. anemoi/datasets/create/sources/tendencies.py +2 -5
  49. anemoi/datasets/create/sources/xarray.py +4 -6
  50. anemoi/datasets/create/sources/xarray_support/__init__.py +12 -13
  51. anemoi/datasets/create/sources/xarray_support/coordinates.py +8 -12
  52. anemoi/datasets/create/sources/xarray_support/field.py +16 -12
  53. anemoi/datasets/create/sources/xarray_support/fieldlist.py +11 -15
  54. anemoi/datasets/create/sources/xarray_support/flavour.py +42 -42
  55. anemoi/datasets/create/sources/xarray_support/grid.py +15 -9
  56. anemoi/datasets/create/sources/xarray_support/metadata.py +19 -128
  57. anemoi/datasets/create/sources/xarray_support/patch.py +4 -6
  58. anemoi/datasets/create/sources/xarray_support/time.py +10 -13
  59. anemoi/datasets/create/sources/xarray_support/variable.py +21 -21
  60. anemoi/datasets/create/sources/xarray_zarr.py +1 -2
  61. anemoi/datasets/create/sources/zenodo.py +3 -5
  62. anemoi/datasets/create/statistics/__init__.py +3 -6
  63. anemoi/datasets/create/testing.py +4 -0
  64. anemoi/datasets/create/typing.py +1 -2
  65. anemoi/datasets/create/utils.py +1 -2
  66. anemoi/datasets/create/zarr.py +7 -2
  67. anemoi/datasets/data/__init__.py +15 -6
  68. anemoi/datasets/data/complement.py +7 -12
  69. anemoi/datasets/data/concat.py +5 -8
  70. anemoi/datasets/data/dataset.py +42 -47
  71. anemoi/datasets/data/debug.py +7 -9
  72. anemoi/datasets/data/ensemble.py +4 -6
  73. anemoi/datasets/data/fill_missing.py +7 -10
  74. anemoi/datasets/data/forwards.py +22 -26
  75. anemoi/datasets/data/grids.py +12 -16
  76. anemoi/datasets/data/indexing.py +9 -12
  77. anemoi/datasets/data/interpolate.py +7 -15
  78. anemoi/datasets/data/join.py +8 -12
  79. anemoi/datasets/data/masked.py +6 -11
  80. anemoi/datasets/data/merge.py +5 -9
  81. anemoi/datasets/data/misc.py +41 -45
  82. anemoi/datasets/data/missing.py +11 -16
  83. anemoi/datasets/data/observations/__init__.py +8 -14
  84. anemoi/datasets/data/padded.py +3 -5
  85. anemoi/datasets/data/records/backends/__init__.py +2 -2
  86. anemoi/datasets/data/rescale.py +5 -12
  87. anemoi/datasets/data/select.py +13 -16
  88. anemoi/datasets/data/statistics.py +4 -7
  89. anemoi/datasets/data/stores.py +16 -21
  90. anemoi/datasets/data/subset.py +8 -11
  91. anemoi/datasets/data/unchecked.py +7 -11
  92. anemoi/datasets/data/xy.py +25 -21
  93. anemoi/datasets/dates/__init__.py +13 -18
  94. anemoi/datasets/dates/groups.py +7 -10
  95. anemoi/datasets/grids.py +5 -9
  96. anemoi/datasets/testing.py +93 -7
  97. anemoi/datasets/validate.py +598 -0
  98. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/METADATA +4 -4
  99. anemoi_datasets-0.5.27.dist-info/RECORD +134 -0
  100. anemoi/datasets/utils/__init__.py +0 -8
  101. anemoi_datasets-0.5.26.dist-info/RECORD +0 -131
  102. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/WHEEL +0 -0
  103. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/entry_points.txt +0 -0
  104. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/licenses/LICENSE +0 -0
  105. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/top_level.txt +0 -0
@@ -12,8 +12,6 @@ import logging
12
12
  import os
13
13
  from copy import deepcopy
14
14
  from typing import Any
15
- from typing import Optional
16
- from typing import Union
17
15
 
18
16
  import yaml
19
17
  from anemoi.utils.config import DotDict
@@ -25,7 +23,7 @@ from anemoi.datasets.dates.groups import Groups
25
23
  LOG = logging.getLogger(__name__)
26
24
 
27
25
 
28
- def _get_first_key_if_dict(x: Union[str, dict]) -> str:
26
+ def _get_first_key_if_dict(x: str | dict) -> str:
29
27
  """Returns the first key if the input is a dictionary, otherwise returns the input string.
30
28
 
31
29
  Parameters
@@ -97,7 +95,7 @@ def check_dict_value_and_set(dic: dict, key: str, value: Any) -> None:
97
95
  dic[key] = value
98
96
 
99
97
 
100
- def resolve_includes(config: Union[dict, list]) -> Union[dict, list]:
98
+ def resolve_includes(config: dict | list) -> dict | list:
101
99
  """Resolves '<<' includes in a configuration dictionary or list.
102
100
 
103
101
  Parameters
@@ -123,7 +121,7 @@ def resolve_includes(config: Union[dict, list]) -> Union[dict, list]:
123
121
  class Config(DotDict):
124
122
  """Configuration class that extends DotDict to handle configuration loading and processing."""
125
123
 
126
- def __init__(self, config: Optional[Union[str, dict]] = None, **kwargs):
124
+ def __init__(self, config: str | dict | None = None, **kwargs):
127
125
  """Initializes the Config object.
128
126
 
129
127
  Parameters
@@ -134,7 +132,6 @@ class Config(DotDict):
134
132
  Additional keyword arguments to update the configuration.
135
133
  """
136
134
  if isinstance(config, str):
137
- self.config_path = os.path.realpath(config)
138
135
  config = load_any_dict_format(config)
139
136
  else:
140
137
  config = deepcopy(config if config is not None else {})
@@ -8,7 +8,6 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
  from typing import Any
11
- from typing import Dict
12
11
 
13
12
  import earthkit.data as ekd
14
13
 
@@ -26,7 +25,7 @@ class TransformFilter:
26
25
  The configuration for the filter.
27
26
  """
28
27
 
29
- def __init__(self, context: Any, name: str, config: Dict[str, Any]) -> None:
28
+ def __init__(self, context: Any, name: str, config: dict[str, Any]) -> None:
30
29
  from anemoi.transform.filters import create_filter
31
30
 
32
31
  self.name = name
@@ -10,7 +10,6 @@
10
10
  import logging
11
11
  from copy import deepcopy
12
12
  from typing import Any
13
- from typing import Union
14
13
 
15
14
  from anemoi.datasets.dates.groups import GroupOfDates
16
15
 
@@ -28,7 +27,7 @@ class Context:
28
27
  class InputBuilder:
29
28
  """Builder class for creating input data from configuration and data sources."""
30
29
 
31
- def __init__(self, config: dict, data_sources: Union[dict, list], **kwargs: Any) -> None:
30
+ def __init__(self, config: dict, data_sources: dict | list, **kwargs: Any) -> None:
32
31
  """Initialize the InputBuilder.
33
32
 
34
33
  Parameters
@@ -11,8 +11,6 @@ import json
11
11
  import logging
12
12
  from copy import deepcopy
13
13
  from typing import Any
14
- from typing import Dict
15
- from typing import List
16
14
 
17
15
  from earthkit.data.core.order import build_remapping
18
16
 
@@ -39,7 +37,7 @@ class Action:
39
37
  """
40
38
 
41
39
  def __init__(
42
- self, context: "ActionContext", action_path: List[str], /, *args: Any, **kwargs: Dict[str, Any]
40
+ self, context: "ActionContext", action_path: list[str], /, *args: Any, **kwargs: dict[str, Any]
43
41
  ) -> None:
44
42
  """Initialize an Action instance.
45
43
 
@@ -175,7 +173,7 @@ class ActionContext(Context):
175
173
  Whether to use GRIB parameter ID.
176
174
  """
177
175
 
178
- def __init__(self, /, order_by: str, flatten_grid: bool, remapping: Dict[str, Any], use_grib_paramid: bool) -> None:
176
+ def __init__(self, /, order_by: str, flatten_grid: bool, remapping: dict[str, Any], use_grib_paramid: bool) -> None:
179
177
  """Initialize an ActionContext instance.
180
178
 
181
179
  Parameters
@@ -196,7 +194,7 @@ class ActionContext(Context):
196
194
  self.use_grib_paramid = use_grib_paramid
197
195
 
198
196
 
199
- def action_factory(config: Dict[str, Any], context: ActionContext, action_path: List[str]) -> Action:
197
+ def action_factory(config: dict[str, Any], context: ActionContext, action_path: list[str]) -> Action:
200
198
  """Factory function to create an Action instance based on the configuration.
201
199
 
202
200
  Parameters
@@ -11,9 +11,6 @@ import logging
11
11
  from copy import deepcopy
12
12
  from functools import cached_property
13
13
  from typing import Any
14
- from typing import Dict
15
- from typing import List
16
- from typing import Union
17
14
 
18
15
  from earthkit.data import FieldList
19
16
 
@@ -39,9 +36,9 @@ class ConcatResult(Result):
39
36
  def __init__(
40
37
  self,
41
38
  context: object,
42
- action_path: List[str],
39
+ action_path: list[str],
43
40
  group_of_dates: GroupOfDates,
44
- results: List[Result],
41
+ results: list[Result],
45
42
  **kwargs: Any,
46
43
  ) -> None:
47
44
  """Initializes a ConcatResult instance.
@@ -74,7 +71,7 @@ class ConcatResult(Result):
74
71
  return _tidy(ds)
75
72
 
76
73
  @property
77
- def variables(self) -> List[str]:
74
+ def variables(self) -> list[str]:
78
75
  """Returns the list of variables, ensuring all results have the same variables."""
79
76
  variables = None
80
77
  for f in self.results:
@@ -101,7 +98,7 @@ class ConcatResult(Result):
101
98
  class ConcatAction(Action):
102
99
  """Represents an action that concatenates multiple actions based on their dates."""
103
100
 
104
- def __init__(self, context: object, action_path: List[str], *configs: Dict[str, Any]) -> None:
101
+ def __init__(self, context: object, action_path: list[str], *configs: dict[str, Any]) -> None:
105
102
  """Initializes a ConcatAction instance.
106
103
 
107
104
  Parameters
@@ -138,7 +135,7 @@ class ConcatAction(Action):
138
135
  return self._repr(content)
139
136
 
140
137
  @trace_select
141
- def select(self, group_of_dates: GroupOfDates) -> Union[ConcatResult, EmptyResult]:
138
+ def select(self, group_of_dates: GroupOfDates) -> ConcatResult | EmptyResult:
142
139
  """Selects the concatenated result for the given group of dates.
143
140
 
144
141
  Parameters
@@ -10,9 +10,6 @@
10
10
  import logging
11
11
  import textwrap
12
12
  from typing import Any
13
- from typing import List
14
- from typing import Tuple
15
- from typing import Union
16
13
 
17
14
  from anemoi.utils.humanize import plural
18
15
 
@@ -32,7 +29,7 @@ class Context:
32
29
  # results is a dictionary of reference path -> obj
33
30
  self.results = {}
34
31
 
35
- def will_need_reference(self, key: Union[List, Tuple]) -> None:
32
+ def will_need_reference(self, key: list | tuple) -> None:
36
33
  """Marks a reference as needed.
37
34
 
38
35
  Parameters
@@ -44,7 +41,7 @@ class Context:
44
41
  key = tuple(key)
45
42
  self.used_references.add(key)
46
43
 
47
- def notify_result(self, key: Union[List, Tuple], result: Any) -> None:
44
+ def notify_result(self, key: list | tuple, result: Any) -> None:
48
45
  """Notifies that a result is available for a reference.
49
46
 
50
47
  Parameters
@@ -68,7 +65,7 @@ class Context:
68
65
  raise ValueError(f"Duplicate result {key}")
69
66
  self.results[key] = result
70
67
 
71
- def get_result(self, key: Union[List, Tuple]) -> Any:
68
+ def get_result(self, key: list | tuple) -> Any:
72
69
  """Retrieves the result for a given reference.
73
70
 
74
71
  Parameters
@@ -10,9 +10,6 @@
10
10
  import logging
11
11
  from functools import cached_property
12
12
  from typing import Any
13
- from typing import Dict
14
- from typing import List
15
- from typing import Union
16
13
 
17
14
  from earthkit.data import FieldList
18
15
 
@@ -31,9 +28,9 @@ class DataSourcesAction(Action):
31
28
  def __init__(
32
29
  self,
33
30
  context: object,
34
- action_path: List[str],
35
- sources: Union[Dict[str, Any], List[Dict[str, Any]]],
36
- input: Dict[str, Any],
31
+ action_path: list[str],
32
+ sources: dict[str, Any] | list[dict[str, Any]],
33
+ input: dict[str, Any],
37
34
  ) -> None:
38
35
  """Initializes a DataSourcesAction instance.
39
36
 
@@ -93,10 +90,10 @@ class DataSourcesResult(Result):
93
90
  def __init__(
94
91
  self,
95
92
  context: object,
96
- action_path: List[str],
93
+ action_path: list[str],
97
94
  dates: object,
98
95
  input_result: Result,
99
- sources_results: List[Result],
96
+ sources_results: list[Result],
100
97
  ) -> None:
101
98
  """Initializes a DataSourcesResult instance.
102
99
 
@@ -9,7 +9,6 @@
9
9
 
10
10
  import logging
11
11
  from functools import cached_property
12
- from typing import List
13
12
 
14
13
  from earthkit.data import FieldList
15
14
 
@@ -49,6 +48,6 @@ class EmptyResult(Result):
49
48
  return from_source("empty")
50
49
 
51
50
  @property
52
- def variables(self) -> List[str]:
51
+ def variables(self) -> list[str]:
53
52
  """Returns an empty list of variables."""
54
53
  return []
@@ -10,7 +10,6 @@
10
10
  import logging
11
11
  from functools import cached_property
12
12
  from typing import Any
13
- from typing import Type
14
13
 
15
14
  from earthkit.data import FieldList
16
15
 
@@ -40,7 +39,7 @@ class FilterStepResult(StepResult):
40
39
  class FilterStepAction(StepAction):
41
40
  """Represents an action to filter a step result."""
42
41
 
43
- result_class: Type[FilterStepResult] = FilterStepResult
42
+ result_class: type[FilterStepResult] = FilterStepResult
44
43
 
45
44
 
46
45
  class StepFunctionResult(StepResult):
@@ -86,7 +85,7 @@ class StepFunctionResult(StepResult):
86
85
  class FunctionStepAction(StepAction):
87
86
  """Represents an action to apply a function to a step result."""
88
87
 
89
- result_class: Type[StepFunctionResult] = StepFunctionResult
88
+ result_class: type[StepFunctionResult] = StepFunctionResult
90
89
 
91
90
  def __init__(
92
91
  self,
@@ -10,7 +10,6 @@
10
10
  import logging
11
11
  from functools import cached_property
12
12
  from typing import Any
13
- from typing import Dict
14
13
 
15
14
  from earthkit.data import FieldList
16
15
 
@@ -91,7 +90,7 @@ class FunctionAction(Action):
91
90
  The name of the function.
92
91
  """
93
92
 
94
- def __init__(self, context: object, action_path: list, _name: str, source, **kwargs: Dict[str, Any]) -> None:
93
+ def __init__(self, context: object, action_path: list, _name: str, source, **kwargs: dict[str, Any]) -> None:
95
94
  """Initializes a FunctionAction instance.
96
95
 
97
96
  Parameters
@@ -10,7 +10,6 @@
10
10
  import logging
11
11
  from functools import cached_property
12
12
  from typing import Any
13
- from typing import List
14
13
 
15
14
  from earthkit.data import FieldList
16
15
 
@@ -44,7 +43,7 @@ class JoinResult(Result):
44
43
  """
45
44
 
46
45
  def __init__(
47
- self, context: object, action_path: list, group_of_dates: GroupOfDates, results: List[Result], **kwargs: Any
46
+ self, context: object, action_path: list, group_of_dates: GroupOfDates, results: list[Result], **kwargs: Any
48
47
  ) -> None:
49
48
  """Initializes a JoinResult instance.
50
49
 
@@ -60,7 +59,7 @@ class JoinResult(Result):
60
59
  The list of results.
61
60
  """
62
61
  super().__init__(context, action_path, group_of_dates)
63
- self.results: List[Result] = [r for r in results if not r.empty]
62
+ self.results: list[Result] = [r for r in results if not r.empty]
64
63
 
65
64
  @cached_property
66
65
  @assert_fieldlist
@@ -105,7 +104,7 @@ class JoinAction(Action):
105
104
  The configuration dictionaries.
106
105
  """
107
106
  super().__init__(context, action_path, *configs)
108
- self.actions: List[Action] = [action_factory(c, context, action_path + [str(i)]) for i, c in enumerate(configs)]
107
+ self.actions: list[Action] = [action_factory(c, context, action_path + [str(i)]) for i, c in enumerate(configs)]
109
108
 
110
109
  def __repr__(self) -> str:
111
110
  """Returns a string representation of the JoinAction instance."""
@@ -126,5 +125,5 @@ class JoinAction(Action):
126
125
  JoinResult
127
126
  The combined result for the given group of dates.
128
127
  """
129
- results: List[Result] = [a.select(group_of_dates) for a in self.actions]
128
+ results: list[Result] = [a.select(group_of_dates) for a in self.actions]
130
129
  return JoinResult(self.context, self.action_path, group_of_dates, results)
@@ -8,11 +8,9 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
  import logging
11
+ from collections.abc import Callable
11
12
  from functools import wraps
12
13
  from typing import Any
13
- from typing import Callable
14
- from typing import Tuple
15
- from typing import Union
16
14
 
17
15
  from earthkit.data import FieldList
18
16
  from earthkit.data.core.fieldlist import MultiFieldList
@@ -20,7 +18,7 @@ from earthkit.data.core.fieldlist import MultiFieldList
20
18
  LOG = logging.getLogger(__name__)
21
19
 
22
20
 
23
- def parse_function_name(name: str) -> Tuple[str, Union[int, None]]:
21
+ def parse_function_name(name: str) -> tuple[str, int | None]:
24
22
  """Parses a function name to extract the base name and an optional time delta.
25
23
 
26
24
  Parameters
@@ -88,7 +86,7 @@ def assert_is_fieldlist(obj: object) -> None:
88
86
  assert isinstance(obj, FieldList), type(obj)
89
87
 
90
88
 
91
- def _flatten(ds: Union[MultiFieldList, FieldList]) -> list:
89
+ def _flatten(ds: MultiFieldList | FieldList) -> list:
92
90
  """Flattens a MultiFieldList or FieldList into a list of FieldList objects.
93
91
 
94
92
  Parameters
@@ -106,7 +104,7 @@ def _flatten(ds: Union[MultiFieldList, FieldList]) -> list:
106
104
  return [ds]
107
105
 
108
106
 
109
- def _tidy(ds: Union[MultiFieldList, FieldList], indent: int = 0) -> Union[MultiFieldList, FieldList]:
107
+ def _tidy(ds: MultiFieldList | FieldList, indent: int = 0) -> MultiFieldList | FieldList:
110
108
  """Tidies up a MultiFieldList or FieldList by removing empty sources.
111
109
 
112
110
  Parameters
@@ -10,13 +10,8 @@
10
10
 
11
11
  import logging
12
12
  from collections import defaultdict
13
+ from collections.abc import Generator
13
14
  from typing import Any
14
- from typing import Dict
15
- from typing import Generator
16
- from typing import List
17
- from typing import Optional
18
- from typing import Set
19
- from typing import Tuple
20
15
 
21
16
  import numpy as np
22
17
  from anemoi.transform.fields import new_field_with_valid_datetime
@@ -37,7 +32,7 @@ class DateMapper:
37
32
  """A factory class to create DateMapper instances based on the given mode."""
38
33
 
39
34
  @staticmethod
40
- def from_mode(mode: str, source: Any, config: Dict[str, Any]) -> "DateMapper":
35
+ def from_mode(mode: str, source: Any, config: dict[str, Any]) -> "DateMapper":
41
36
  """Create a DateMapper instance based on the given mode.
42
37
 
43
38
  Parameters
@@ -87,10 +82,10 @@ class DateMapperClosest(DateMapper):
87
82
  self.maximum: Any = frequency_to_timedelta(maximum)
88
83
  self.frequency: Any = frequency_to_timedelta(frequency)
89
84
  self.skip_all_nans: bool = skip_all_nans
90
- self.tried: Set[Any] = set()
91
- self.found: Set[Any] = set()
85
+ self.tried: set[Any] = set()
86
+ self.found: set[Any] = set()
92
87
 
93
- def transform(self, group_of_dates: Any) -> Generator[Tuple[Any, Any], None, None]:
88
+ def transform(self, group_of_dates: Any) -> Generator[tuple[Any, Any], None, None]:
94
89
  """Transform the group of dates to the closest available dates.
95
90
 
96
91
  Parameters
@@ -185,7 +180,7 @@ class DateMapperClosest(DateMapper):
185
180
  class DateMapperClimatology(DateMapper):
186
181
  """A DateMapper implementation that maps dates to specified climatology dates."""
187
182
 
188
- def __init__(self, source: Any, year: int, day: int, hour: Optional[int] = None) -> None:
183
+ def __init__(self, source: Any, year: int, day: int, hour: int | None = None) -> None:
189
184
  """Initialize DateMapperClimatology.
190
185
 
191
186
  Parameters
@@ -201,9 +196,9 @@ class DateMapperClimatology(DateMapper):
201
196
  """
202
197
  self.year: int = year
203
198
  self.day: int = day
204
- self.hour: Optional[int] = hour
199
+ self.hour: int | None = hour
205
200
 
206
- def transform(self, group_of_dates: Any) -> Generator[Tuple[Any, Any], None, None]:
201
+ def transform(self, group_of_dates: Any) -> Generator[tuple[Any, Any], None, None]:
207
202
  """Transform the group of dates to the specified climatology dates.
208
203
 
209
204
  Parameters
@@ -239,7 +234,7 @@ class DateMapperClimatology(DateMapper):
239
234
  class DateMapperConstant(DateMapper):
240
235
  """A DateMapper implementation that maps dates to a constant date."""
241
236
 
242
- def __init__(self, source: Any, date: Optional[Any] = None) -> None:
237
+ def __init__(self, source: Any, date: Any | None = None) -> None:
243
238
  """Initialize DateMapperConstant.
244
239
 
245
240
  Parameters
@@ -250,9 +245,9 @@ class DateMapperConstant(DateMapper):
250
245
  The constant date to map to.
251
246
  """
252
247
  self.source: Any = source
253
- self.date: Optional[Any] = date
248
+ self.date: Any | None = date
254
249
 
255
- def transform(self, group_of_dates: Any) -> Tuple[Any, Any]:
250
+ def transform(self, group_of_dates: Any) -> tuple[Any, Any]:
256
251
  """Transform the group of dates to a constant date.
257
252
 
258
253
  Parameters
@@ -289,7 +284,7 @@ class DateMapperResult(Result):
289
284
  def __init__(
290
285
  self,
291
286
  context: Any,
292
- action_path: List[str],
287
+ action_path: list[str],
293
288
  group_of_dates: Any,
294
289
  source_result: Any,
295
290
  mapper: DateMapper,
@@ -336,7 +331,7 @@ class DateMapperResult(Result):
336
331
  class RepeatedDatesAction(Action):
337
332
  """An Action implementation that selects and transforms a group of dates."""
338
333
 
339
- def __init__(self, context: Any, action_path: List[str], source: Any, mode: str, **kwargs: Any) -> None:
334
+ def __init__(self, context: Any, action_path: list[str], source: Any, mode: str, **kwargs: Any) -> None:
340
335
  """Initialize RepeatedDatesAction.
341
336
 
342
337
  Args: