anemoi-utils 0.4.29__py3-none-any.whl → 0.4.30__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.

Potentially problematic release.


This version of anemoi-utils might be problematic. Click here for more details.

anemoi/utils/humanize.py CHANGED
@@ -15,14 +15,9 @@ import json
15
15
  import re
16
16
  import warnings
17
17
  from collections import defaultdict
18
+ from collections.abc import Callable
19
+ from collections.abc import Generator
18
20
  from typing import Any
19
- from typing import Callable
20
- from typing import Dict
21
- from typing import Generator
22
- from typing import List
23
- from typing import Optional
24
- from typing import Tuple
25
- from typing import Union
26
21
 
27
22
  from anemoi.utils.dates import as_datetime
28
23
 
@@ -57,7 +52,7 @@ def bytes_to_human(n: float) -> str:
57
52
  while n >= 1024:
58
53
  n /= 1024.0
59
54
  i += 1
60
- return "%s%g%s" % (sign, int(n * 10 + 0.5) / 10.0, u[i])
55
+ return f"{sign}{int(n * 10 + 0.5) / 10.0:g}{u[i]}"
61
56
 
62
57
 
63
58
  def bytes(n: float) -> str:
@@ -99,7 +94,7 @@ def base2_to_human(n: float) -> str:
99
94
  while n >= 1024:
100
95
  n /= 1024.0
101
96
  i += 1
102
- return "%g%s" % (int(n * 10 + 0.5) / 10.0, u[i])
97
+ return f"{int(n * 10 + 0.5) / 10.0:g}{u[i]}"
103
98
 
104
99
 
105
100
  def base2(n: float) -> str:
@@ -151,7 +146,7 @@ def _plural(count: int) -> str:
151
146
  return ""
152
147
 
153
148
 
154
- def seconds_to_human(seconds: Union[float, datetime.timedelta]) -> str:
149
+ def seconds_to_human(seconds: float | datetime.timedelta) -> str:
155
150
  """Convert a number of seconds to a human readable string.
156
151
 
157
152
  >>> seconds_to_human(4000)
@@ -205,7 +200,7 @@ def seconds_to_human(seconds: Union[float, datetime.timedelta]) -> str:
205
200
 
206
201
  if not s:
207
202
  seconds = round(seconds * 10) / 10
208
- s.append("%g second%s" % (seconds, _plural(seconds)))
203
+ s.append(f"{seconds:g} second{_plural(seconds)}")
209
204
  return " ".join(s)
210
205
 
211
206
 
@@ -303,7 +298,7 @@ def __(n: int) -> str:
303
298
 
304
299
 
305
300
  def when(
306
- then: datetime.datetime, now: Optional[datetime.datetime] = None, short: bool = True, use_utc: bool = False
301
+ then: datetime.datetime, now: datetime.datetime | None = None, short: bool = True, use_utc: bool = False
307
302
  ) -> str:
308
303
  """Generate a human readable string for a date, relative to now.
309
304
 
@@ -359,23 +354,23 @@ def when(
359
354
 
360
355
  def _(x):
361
356
  if last == "last":
362
- return "%s ago" % (x,)
357
+ return f"{x} ago"
363
358
  else:
364
- return "in %s" % (x,)
359
+ return f"in {x}"
365
360
 
366
361
  if diff < 60:
367
362
  diff = int(diff + 0.5)
368
- return _("%s second%s" % (diff, _plural(diff)))
363
+ return _(f"{diff} second{_plural(diff)}")
369
364
 
370
365
  if diff < 60 * 60:
371
366
  diff /= 60
372
367
  diff = int(diff + 0.5)
373
- return _("%s minute%s" % (diff, _plural(diff)))
368
+ return _(f"{diff} minute{_plural(diff)}")
374
369
 
375
370
  if diff < 60 * 60 * 6:
376
371
  diff /= 60 * 60
377
372
  diff = int(diff + 0.5)
378
- return _("%s hour%s" % (diff, _plural(diff)))
373
+ return _(f"{diff} hour{_plural(diff)}")
379
374
 
380
375
  jnow = now.toordinal()
381
376
  jthen = then.toordinal()
@@ -392,7 +387,7 @@ def when(
392
387
  if abs(jnow - jthen) <= 7:
393
388
  if last == "next":
394
389
  last = "this"
395
- return "%s %s" % (
390
+ return "{} {}".format(
396
391
  last,
397
392
  DOW[then.weekday()],
398
393
  )
@@ -462,7 +457,7 @@ def string_distance(s: str, t: str) -> int:
462
457
  return d[m, n]
463
458
 
464
459
 
465
- def did_you_mean(word: str, vocabulary: List[str]) -> str:
460
+ def did_you_mean(word: str, vocabulary: list[str]) -> str:
466
461
  """Pick the closest word in a vocabulary.
467
462
 
468
463
  >>> did_you_mean("aple", ["banana", "lemon", "apple", "orange"])
@@ -485,7 +480,7 @@ def did_you_mean(word: str, vocabulary: List[str]) -> str:
485
480
  return best
486
481
 
487
482
 
488
- def dict_to_human(query: Dict[str, Any]) -> str:
483
+ def dict_to_human(query: dict[str, Any]) -> str:
489
484
  """Convert a dictionary to a human readable string.
490
485
 
491
486
  Parameters
@@ -503,7 +498,7 @@ def dict_to_human(query: Dict[str, Any]) -> str:
503
498
  return list_to_human(lst)
504
499
 
505
500
 
506
- def list_to_human(lst: List[str], conjunction: str = "and") -> str:
501
+ def list_to_human(lst: list[str], conjunction: str = "and") -> str:
507
502
  """Convert a list of strings to a human readable string.
508
503
 
509
504
  >>> list_to_human(["banana", "lemon", "apple", "orange"])
@@ -530,7 +525,7 @@ def list_to_human(lst: List[str], conjunction: str = "and") -> str:
530
525
  return f" {conjunction} ".join(lst)
531
526
 
532
527
 
533
- def human_to_number(value: Union[str, int], name: str, units: Dict[str, int], none_ok: bool) -> Optional[int]:
528
+ def human_to_number(value: str | int, name: str, units: dict[str, int], none_ok: bool) -> int | None:
534
529
  """Convert a human readable string to a number.
535
530
 
536
531
  Parameters
@@ -568,8 +563,8 @@ def human_to_number(value: Union[str, int], name: str, units: Dict[str, int], no
568
563
 
569
564
 
570
565
  def as_number(
571
- value: Union[str, int], name: Optional[str] = None, units: Optional[Dict[str, int]] = None, none_ok: bool = False
572
- ) -> Optional[int]:
566
+ value: str | int, name: str | None = None, units: dict[str, int] | None = None, none_ok: bool = False
567
+ ) -> int | None:
573
568
  """Deprecated function to convert a human readable string to a number.
574
569
 
575
570
  Parameters
@@ -596,7 +591,7 @@ def as_number(
596
591
  return human_to_number(value, name, units, none_ok)
597
592
 
598
593
 
599
- def human_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
594
+ def human_seconds(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
600
595
  """Convert a human readable string to seconds.
601
596
 
602
597
  Parameters
@@ -617,7 +612,7 @@ def human_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: b
617
612
  return human_to_number(value, name, units, none_ok)
618
613
 
619
614
 
620
- def as_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
615
+ def as_seconds(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
621
616
  """Deprecated function to convert a human readable string to seconds.
622
617
 
623
618
  Parameters
@@ -642,7 +637,7 @@ def as_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: bool
642
637
  return human_seconds(value, name, none_ok)
643
638
 
644
639
 
645
- def human_to_percent(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
640
+ def human_to_percent(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
646
641
  """Convert a human readable string to a percentage.
647
642
 
648
643
  Parameters
@@ -663,7 +658,7 @@ def human_to_percent(value: Union[str, int], name: Optional[str] = None, none_ok
663
658
  return human_to_number(value, name, units, none_ok)
664
659
 
665
660
 
666
- def as_percent(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
661
+ def as_percent(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
667
662
  """Deprecated function to convert a human readable string to a percentage.
668
663
 
669
664
  Parameters
@@ -688,7 +683,7 @@ def as_percent(value: Union[str, int], name: Optional[str] = None, none_ok: bool
688
683
  return human_to_percent(value, name, none_ok)
689
684
 
690
685
 
691
- def human_to_bytes(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
686
+ def human_to_bytes(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
692
687
  """Convert a human readable string to bytes.
693
688
 
694
689
  Parameters
@@ -715,7 +710,7 @@ def human_to_bytes(value: Union[str, int], name: Optional[str] = None, none_ok:
715
710
  return human_to_number(value, name, units, none_ok)
716
711
 
717
712
 
718
- def as_bytes(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
713
+ def as_bytes(value: str | int, name: str | None = None, none_ok: bool = False) -> int | None:
719
714
  """Deprecated function to convert a human readable string to bytes.
720
715
 
721
716
  Parameters
@@ -740,7 +735,7 @@ def as_bytes(value: Union[str, int], name: Optional[str] = None, none_ok: bool =
740
735
  return human_to_bytes(value, name, none_ok)
741
736
 
742
737
 
743
- def human_to_timedelta(value: str, name: Optional[str] = None, none_ok: bool = False) -> datetime.timedelta:
738
+ def human_to_timedelta(value: str, name: str | None = None, none_ok: bool = False) -> datetime.timedelta:
744
739
  """Convert a human readable string to a timedelta.
745
740
 
746
741
  Parameters
@@ -792,7 +787,7 @@ def human_to_timedelta(value: str, name: Optional[str] = None, none_ok: bool = F
792
787
  )
793
788
 
794
789
 
795
- def as_timedelta(value: str, name: Optional[str] = None, none_ok: bool = False) -> datetime.timedelta:
790
+ def as_timedelta(value: str, name: str | None = None, none_ok: bool = False) -> datetime.timedelta:
796
791
  """Deprecated function to convert a human readable string to a timedelta.
797
792
 
798
793
  Parameters
@@ -892,7 +887,7 @@ def json_pretty_dump(obj: Any, max_line_length: int = 120, default: Callable = s
892
887
  return _format_json(obj)
893
888
 
894
889
 
895
- def shorten_list(lst: Union[List[Any], Tuple[Any]], max_length: int = 5) -> Union[List[Any], Tuple[Any]]:
890
+ def shorten_list(lst: list[Any] | tuple[Any], max_length: int = 5) -> list[Any] | tuple[Any]:
896
891
  """Shorten a list to a maximum length.
897
892
 
898
893
  Parameters
@@ -918,10 +913,8 @@ def shorten_list(lst: Union[List[Any], Tuple[Any]], max_length: int = 5) -> Unio
918
913
 
919
914
 
920
915
  def _compress_dates(
921
- dates: List[datetime.datetime],
922
- ) -> Generator[
923
- Union[List[datetime.datetime], Tuple[datetime.datetime, datetime.datetime, datetime.timedelta]], None, None
924
- ]:
916
+ dates: list[datetime.datetime],
917
+ ) -> Generator[list[datetime.datetime] | tuple[datetime.datetime, datetime.datetime, datetime.timedelta], None, None]:
925
918
  """Compress a list of dates into a more compact representation.
926
919
 
927
920
  Parameters
@@ -953,7 +946,7 @@ def _compress_dates(
953
946
  yield from _compress_dates([curr] + dates)
954
947
 
955
948
 
956
- def compress_dates(dates: List[Union[datetime.datetime, str]]) -> str:
949
+ def compress_dates(dates: list[datetime.datetime | str]) -> str:
957
950
  """Compress a list of dates into a human-readable format.
958
951
 
959
952
  Parameters
@@ -979,7 +972,7 @@ def compress_dates(dates: List[Union[datetime.datetime, str]]) -> str:
979
972
  return result
980
973
 
981
974
 
982
- def print_dates(dates: List[Union[datetime.datetime, str]]) -> None:
975
+ def print_dates(dates: list[datetime.datetime | str]) -> None:
983
976
  """Print a list of dates in a human-readable format.
984
977
 
985
978
  Parameters
@@ -990,7 +983,7 @@ def print_dates(dates: List[Union[datetime.datetime, str]]) -> None:
990
983
  print(compress_dates(dates))
991
984
 
992
985
 
993
- def make_list_int(value: Union[str, List[int], Tuple[int], int]) -> List[int]:
986
+ def make_list_int(value: str | list[int] | tuple[int] | int) -> list[int]:
994
987
  """Convert a string like "1/2/3" or "1/to/3" or "1/to/10/by/2" to a list of integers.
995
988
 
996
989
  Parameters
@@ -17,9 +17,6 @@ import datetime
17
17
  import logging
18
18
  import os
19
19
  from typing import Any
20
- from typing import Dict
21
- from typing import Optional
22
- from typing import Tuple
23
20
 
24
21
  import yaml
25
22
 
@@ -33,7 +30,7 @@ DEFAULT_MARS_LABELLING = {
33
30
  }
34
31
 
35
32
 
36
- def _expand_mars_labelling(request: Dict[str, Any]) -> Dict[str, Any]:
33
+ def _expand_mars_labelling(request: dict[str, Any]) -> dict[str, Any]:
37
34
  """Expand the request with the default Mars labelling.
38
35
 
39
36
  Parameters
@@ -54,7 +51,7 @@ def _expand_mars_labelling(request: Dict[str, Any]) -> Dict[str, Any]:
54
51
  STREAMS = None
55
52
 
56
53
 
57
- def _lookup_mars_stream(request: Dict[str, Any]) -> Optional[Dict[str, Any]]:
54
+ def _lookup_mars_stream(request: dict[str, Any]) -> dict[str, Any] | None:
58
55
  """Look up the Mars stream information for a given request.
59
56
 
60
57
  Parameters
@@ -82,8 +79,8 @@ def _lookup_mars_stream(request: Dict[str, Any]) -> Optional[Dict[str, Any]]:
82
79
 
83
80
 
84
81
  def recenter(
85
- date: datetime.datetime, center: Dict[str, Any], members: Dict[str, Any]
86
- ) -> Tuple[Optional[Dict[str, Any]], Optional[Dict[str, Any]]]:
82
+ date: datetime.datetime, center: dict[str, Any], members: dict[str, Any]
83
+ ) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
87
84
  """Recenter the given date with the specified center and members.
88
85
 
89
86
  Parameters
@@ -7,11 +7,10 @@
7
7
 
8
8
  import sys
9
9
  from typing import Any
10
- from typing import Dict
11
10
  from typing import TextIO
12
11
 
13
12
 
14
- def print_request(verb: str, request: Dict[str, Any], file: TextIO = sys.stdout) -> None:
13
+ def print_request(verb: str, request: dict[str, Any], file: TextIO = sys.stdout) -> None:
15
14
  """Prints a formatted request.
16
15
 
17
16
  Parameters
@@ -25,16 +25,11 @@ import sys
25
25
  import sysconfig
26
26
  from functools import cache
27
27
  from typing import Any
28
- from typing import Dict
29
- from typing import List
30
- from typing import Optional
31
- from typing import Tuple
32
- from typing import Union
33
28
 
34
29
  LOG = logging.getLogger(__name__)
35
30
 
36
31
 
37
- def lookup_git_repo(path: str) -> Optional[Any]:
32
+ def lookup_git_repo(path: str) -> Any | None:
38
33
  """Lookup the git repository for a given path.
39
34
 
40
35
  Parameters
@@ -62,7 +57,7 @@ def lookup_git_repo(path: str) -> Optional[Any]:
62
57
  return None
63
58
 
64
59
 
65
- def _check_for_git(paths: List[Tuple[str, str]], full: bool) -> Dict[str, Any]:
60
+ def _check_for_git(paths: list[tuple[str, str]], full: bool) -> dict[str, Any]:
66
61
  """Check for git information for the given paths.
67
62
 
68
63
  Parameters
@@ -112,7 +107,7 @@ def _check_for_git(paths: List[Tuple[str, str]], full: bool) -> Dict[str, Any]:
112
107
 
113
108
 
114
109
  def version(
115
- versions: Dict[str, Any], name: str, module: Any, roots: Dict[str, str], namespaces: set, paths: set, full: bool
110
+ versions: dict[str, Any], name: str, module: Any, roots: dict[str, str], namespaces: set, paths: set, full: bool
116
111
  ) -> None:
117
112
  """Collect version information for a module.
118
113
 
@@ -174,7 +169,7 @@ def version(
174
169
  versions[name] = str(module)
175
170
 
176
171
 
177
- def _module_versions(full: bool) -> Tuple[Dict[str, Any], set]:
172
+ def _module_versions(full: bool) -> tuple[dict[str, Any], set]:
178
173
  """Collect version information for all loaded modules.
179
174
 
180
175
  Parameters
@@ -216,7 +211,7 @@ def _module_versions(full: bool) -> Tuple[Dict[str, Any], set]:
216
211
 
217
212
 
218
213
  @cache
219
- def package_distributions() -> Dict[str, List[str]]:
214
+ def package_distributions() -> dict[str, list[str]]:
220
215
  """Get the package distributions.
221
216
 
222
217
  Returns
@@ -235,7 +230,7 @@ def package_distributions() -> Dict[str, List[str]]:
235
230
  return metadata.packages_distributions()
236
231
 
237
232
 
238
- def import_name_to_distribution_name(packages: List[str]) -> Dict[str, str]:
233
+ def import_name_to_distribution_name(packages: list[str]) -> dict[str, str]:
239
234
  """Convert import names to distribution names.
240
235
 
241
236
  Parameters
@@ -266,7 +261,7 @@ def import_name_to_distribution_name(packages: List[str]) -> Dict[str, str]:
266
261
  return distribution_names
267
262
 
268
263
 
269
- def module_versions(full: bool) -> Tuple[Dict[str, Any], Dict[str, Any]]:
264
+ def module_versions(full: bool) -> tuple[dict[str, Any], dict[str, Any]]:
270
265
  """Collect version information for all loaded modules and their git information.
271
266
 
272
267
  Parameters
@@ -306,7 +301,7 @@ def _name(obj: Any) -> str:
306
301
  return str(obj)
307
302
 
308
303
 
309
- def _paths(path_or_object: Union[None, str, List[str], Tuple[str], Any]) -> List[Tuple[str, str]]:
304
+ def _paths(path_or_object: None | str | list[str] | tuple[str] | Any) -> list[tuple[str, str]]:
310
305
  """Get the paths for a given path or object.
311
306
 
312
307
  Parameters
@@ -357,7 +352,7 @@ def _paths(path_or_object: Union[None, str, List[str], Tuple[str], Any]) -> List
357
352
  return paths
358
353
 
359
354
 
360
- def git_check(*args: Any) -> Dict[str, Any]:
355
+ def git_check(*args: Any) -> dict[str, Any]:
361
356
  """Return the git information for the given arguments.
362
357
 
363
358
  Arguments can be:
@@ -400,7 +395,7 @@ def git_check(*args: Any) -> Dict[str, Any]:
400
395
  return result
401
396
 
402
397
 
403
- def platform_info() -> Dict[str, Any]:
398
+ def platform_info() -> dict[str, Any]:
404
399
  """Get the platform information.
405
400
 
406
401
  Returns
@@ -429,7 +424,7 @@ def platform_info() -> Dict[str, Any]:
429
424
  return r
430
425
 
431
426
 
432
- def gpu_info() -> Union[str, List[Dict[str, Any]]]:
427
+ def gpu_info() -> str | list[dict[str, Any]]:
433
428
  """Get the GPU information.
434
429
 
435
430
  Returns
@@ -470,7 +465,7 @@ def path_md5(path: str) -> str:
470
465
  return hash.hexdigest()
471
466
 
472
467
 
473
- def assets_info(paths: List[str]) -> Dict[str, Any]:
468
+ def assets_info(paths: list[str]) -> dict[str, Any]:
474
469
  """Get information about the given assets.
475
470
 
476
471
  Parameters
@@ -511,7 +506,7 @@ def assets_info(paths: List[str]) -> Dict[str, Any]:
511
506
  return result
512
507
 
513
508
 
514
- def gather_provenance_info(assets: List[str] = [], full: bool = False) -> Dict[str, Any]:
509
+ def gather_provenance_info(assets: list[str] = [], full: bool = False) -> dict[str, Any]:
515
510
  """Gather information about the current environment.
516
511
 
517
512
  Parameters
anemoi/utils/registry.py CHANGED
@@ -13,15 +13,12 @@ import logging
13
13
  import os
14
14
  import sys
15
15
  import warnings
16
+ from collections.abc import Callable
16
17
  from functools import cached_property
17
18
  from typing import Any
18
- from typing import Callable
19
- from typing import Dict
20
19
  from typing import Generic
21
- from typing import List
22
20
  from typing import Optional
23
21
  from typing import TypeVar
24
- from typing import Union
25
22
 
26
23
  import entrypoints
27
24
 
@@ -121,9 +118,7 @@ class Registry(Generic[T]):
121
118
  """
122
119
  return _BY_KIND.get(kind)
123
120
 
124
- def register(
125
- self, name: str, factory: Optional[Callable] = None, source: Optional[Any] = None
126
- ) -> Optional[Wrapper]:
121
+ def register(self, name: str, factory: Callable | None = None, source: Any | None = None) -> Wrapper | None:
127
122
  """Register a factory with the registry.
128
123
 
129
124
  Parameters
@@ -201,7 +196,7 @@ class Registry(Generic[T]):
201
196
  LOG.info(f"Registered: {e} ({self._sources.get(e)})")
202
197
  return ok
203
198
 
204
- def lookup(self, name: str, *, return_none: bool = False) -> Optional[Callable]:
199
+ def lookup(self, name: str, *, return_none: bool = False) -> Callable | None:
205
200
  """Lookup a factory by name.
206
201
 
207
202
  Parameters
@@ -234,7 +229,7 @@ class Registry(Generic[T]):
234
229
  return factory
235
230
 
236
231
  @cached_property
237
- def factories(self) -> Dict[str, Callable]:
232
+ def factories(self) -> dict[str, Callable]:
238
233
 
239
234
  directory = sys.modules[self.package].__path__[0]
240
235
 
@@ -286,7 +281,7 @@ class Registry(Generic[T]):
286
281
  return self.__registered
287
282
 
288
283
  @property
289
- def registered(self) -> List[str]:
284
+ def registered(self) -> list[str]:
290
285
  """Get the registered factories."""
291
286
 
292
287
  return sorted(self.factories.keys())
@@ -314,7 +309,7 @@ class Registry(Generic[T]):
314
309
  factory = self.lookup(name)
315
310
  return factory(*args, **kwargs)
316
311
 
317
- def from_config(self, config: Union[str, Dict[str, Any]], *args: Any, **kwargs: Any) -> T:
312
+ def from_config(self, config: str | dict[str, Any], *args: Any, **kwargs: Any) -> T:
318
313
  """Create an instance from a configuration.
319
314
 
320
315
  Parameters
@@ -10,9 +10,8 @@ import logging
10
10
  import os
11
11
  import shutil
12
12
  from abc import abstractmethod
13
+ from collections.abc import Iterable
13
14
  from typing import Any
14
- from typing import Dict
15
- from typing import Iterable
16
15
 
17
16
  import tqdm
18
17
 
@@ -496,7 +495,7 @@ class Transfer:
496
495
  if not target:
497
496
  target = os.path.basename(os.path.dirname(source))
498
497
 
499
- temporary_target: Dict[Any, Any] = {
498
+ temporary_target: dict[Any, Any] = {
500
499
  False: None,
501
500
  True: "{dirname}-downloading/{basename}",
502
501
  "-tmp/*": "{dirname}-tmp/{basename}",
anemoi/utils/remote/s3.py CHANGED
@@ -28,9 +28,9 @@ import fnmatch
28
28
  import logging
29
29
  import os
30
30
  import threading
31
+ from collections.abc import Iterable
31
32
  from copy import deepcopy
32
33
  from typing import Any
33
- from typing import Iterable
34
34
 
35
35
  import tqdm
36
36
 
anemoi/utils/rules.py CHANGED
@@ -7,17 +7,13 @@
7
7
  # granted to it by virtue of its status as an intergovernmental organisation
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
+ from collections.abc import Mapping
10
11
  from typing import Any
11
- from typing import Dict
12
- from typing import List
13
- from typing import Mapping
14
- from typing import Optional
15
- from typing import Union
16
12
 
17
13
 
18
14
  class Rule:
19
15
 
20
- def __init__(self, match: Dict[str, Any], result: Any):
16
+ def __init__(self, match: dict[str, Any], result: Any):
21
17
  """Initialize a Rule object.
22
18
 
23
19
  Parameters
@@ -55,14 +51,14 @@ class Rule:
55
51
  return self._result
56
52
 
57
53
  @property
58
- def condition(self) -> Dict[str, Any]:
54
+ def condition(self) -> dict[str, Any]:
59
55
  """The conditions that define the rule."""
60
56
  return self._match
61
57
 
62
58
 
63
59
  class RuleSet:
64
60
 
65
- def __init__(self, rules: List[Union[Rule, Dict[str, Any], List[Any]]]):
61
+ def __init__(self, rules: list[Rule | dict[str, Any] | list[Any]]):
66
62
  """Initialize a RuleSet object.
67
63
 
68
64
  Parameters
@@ -73,7 +69,7 @@ class RuleSet:
73
69
  """
74
70
  assert isinstance(rules, list), "rules must be a list"
75
71
 
76
- self.rules: List[Rule] = []
72
+ self.rules: list[Rule] = []
77
73
 
78
74
  for rule in rules:
79
75
  if isinstance(rule, Rule):
@@ -107,7 +103,7 @@ class RuleSet:
107
103
  )
108
104
 
109
105
  @classmethod
110
- def from_list(cls, rules: List[Any]) -> "RuleSet":
106
+ def from_list(cls, rules: list[Any]) -> "RuleSet":
111
107
  """Create a RuleSet from a list of rules.
112
108
 
113
109
  Parameters
@@ -144,19 +140,19 @@ class RuleSet:
144
140
  if path.endswith(".json"):
145
141
  import json
146
142
 
147
- with open(path, "r") as f:
143
+ with open(path) as f:
148
144
  return cls.from_list(json.load(f))
149
145
 
150
146
  if path.endswith(".yaml") or path.endswith(".yml"):
151
147
  import yaml
152
148
 
153
- with open(path, "r") as f:
149
+ with open(path) as f:
154
150
  return cls.from_list(yaml.safe_load(f))
155
151
 
156
152
  raise ValueError("Unsupported file format. Supported formats are .json and .yaml/.yml.")
157
153
 
158
154
  @classmethod
159
- def from_any(cls, rules: Union[str, List[Any]]) -> "RuleSet":
155
+ def from_any(cls, rules: str | list[Any]) -> "RuleSet":
160
156
  """Create a RuleSet from a list or a file path.
161
157
 
162
158
  Parameters
@@ -182,7 +178,7 @@ class RuleSet:
182
178
 
183
179
  raise ValueError("Unsupported rules format. Must be a list or a file path.")
184
180
 
185
- def match(self, obj: Mapping[str, Any], strategy: str = "first-match") -> Optional[Rule]:
181
+ def match(self, obj: Mapping[str, Any], strategy: str = "first-match") -> Rule | None:
186
182
  """Match an object against the rules in the RuleSet.
187
183
 
188
184
  Parameters
anemoi/utils/s3.py CHANGED
@@ -8,9 +8,8 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
  import warnings
11
+ from collections.abc import Callable
11
12
  from typing import Any
12
- from typing import Callable
13
- from typing import Optional
14
13
 
15
14
  from .remote import transfer
16
15
  from .remote.s3 import delete as delete_
@@ -55,7 +54,7 @@ def upload(
55
54
  overwrite: bool = False,
56
55
  resume: bool = False,
57
56
  verbosity: int = 1,
58
- progress: Optional[Callable] = None,
57
+ progress: Callable | None = None,
59
58
  threads: int = 1,
60
59
  ) -> None:
61
60
  """Upload a file to S3.