anemoi-utils 0.4.12__py3-none-any.whl → 0.4.14__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/__init__.py +1 -0
- anemoi/utils/__main__.py +12 -2
- anemoi/utils/_version.py +9 -4
- anemoi/utils/caching.py +138 -13
- anemoi/utils/checkpoints.py +81 -13
- anemoi/utils/cli.py +83 -7
- anemoi/utils/commands/__init__.py +4 -0
- anemoi/utils/commands/config.py +19 -2
- anemoi/utils/commands/requests.py +18 -2
- anemoi/utils/compatibility.py +6 -5
- anemoi/utils/config.py +254 -23
- anemoi/utils/dates.py +204 -50
- anemoi/utils/devtools.py +68 -7
- anemoi/utils/grib.py +30 -9
- anemoi/utils/grids.py +85 -8
- anemoi/utils/hindcasts.py +25 -8
- anemoi/utils/humanize.py +357 -52
- anemoi/utils/logs.py +31 -3
- anemoi/utils/mars/__init__.py +46 -12
- anemoi/utils/mars/requests.py +15 -1
- anemoi/utils/provenance.py +189 -32
- anemoi/utils/registry.py +234 -44
- anemoi/utils/remote/__init__.py +386 -38
- anemoi/utils/remote/s3.py +252 -29
- anemoi/utils/remote/ssh.py +140 -8
- anemoi/utils/s3.py +77 -4
- anemoi/utils/sanitise.py +52 -7
- anemoi/utils/testing.py +182 -0
- anemoi/utils/text.py +218 -54
- anemoi/utils/timer.py +91 -15
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/METADATA +8 -4
- anemoi_utils-0.4.14.dist-info/RECORD +38 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/WHEEL +1 -1
- anemoi_utils-0.4.12.dist-info/RECORD +0 -37
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/entry_points.txt +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info/licenses}/LICENSE +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/top_level.txt +0 -0
anemoi/utils/humanize.py
CHANGED
|
@@ -8,43 +8,44 @@
|
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
"""Generate human readable strings"""
|
|
11
|
+
"""Generate human readable strings."""
|
|
12
12
|
|
|
13
13
|
import datetime
|
|
14
14
|
import json
|
|
15
15
|
import re
|
|
16
16
|
import warnings
|
|
17
17
|
from collections import defaultdict
|
|
18
|
+
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
|
|
18
26
|
|
|
19
27
|
from anemoi.utils.dates import as_datetime
|
|
20
28
|
|
|
21
29
|
|
|
22
30
|
def bytes_to_human(n: float) -> str:
|
|
23
|
-
"""Convert a number of bytes to a human readable string
|
|
31
|
+
"""Convert a number of bytes to a human readable string.
|
|
24
32
|
|
|
25
|
-
>>>
|
|
33
|
+
>>> bytes_to_human(4096)
|
|
26
34
|
'4 KiB'
|
|
27
35
|
|
|
28
|
-
>>>
|
|
36
|
+
>>> bytes_to_human(4000)
|
|
29
37
|
'3.9 KiB'
|
|
30
38
|
|
|
31
39
|
Parameters
|
|
32
40
|
----------
|
|
33
41
|
n : float
|
|
34
|
-
|
|
42
|
+
The number of bytes
|
|
35
43
|
|
|
36
44
|
Returns
|
|
37
45
|
-------
|
|
38
46
|
str
|
|
39
|
-
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
A human readable string
|
|
46
48
|
"""
|
|
47
|
-
|
|
48
49
|
if n < 0:
|
|
49
50
|
sign = "-"
|
|
50
51
|
n -= 0
|
|
@@ -60,6 +61,18 @@ def bytes_to_human(n: float) -> str:
|
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
def bytes(n: float) -> str:
|
|
64
|
+
"""Deprecated function to convert bytes to a human readable string.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
n : float
|
|
69
|
+
The number of bytes
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
str
|
|
74
|
+
A human readable string
|
|
75
|
+
"""
|
|
63
76
|
warnings.warn(
|
|
64
77
|
"Function bytes is deprecated and will be removed in a future version. Use bytes_to_human instead.",
|
|
65
78
|
category=DeprecationWarning,
|
|
@@ -68,8 +81,19 @@ def bytes(n: float) -> str:
|
|
|
68
81
|
return bytes_to_human(n)
|
|
69
82
|
|
|
70
83
|
|
|
71
|
-
def base2_to_human(n) -> str:
|
|
84
|
+
def base2_to_human(n: float) -> str:
|
|
85
|
+
"""Convert a number to a human readable string using base 2 units.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
n : float
|
|
90
|
+
The number to convert
|
|
72
91
|
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
str
|
|
95
|
+
A human readable string
|
|
96
|
+
"""
|
|
73
97
|
u = ["", "K", "M", "G", "T", " P", "E", "Z", "Y"]
|
|
74
98
|
i = 0
|
|
75
99
|
while n >= 1024:
|
|
@@ -78,8 +102,19 @@ def base2_to_human(n) -> str:
|
|
|
78
102
|
return "%g%s" % (int(n * 10 + 0.5) / 10.0, u[i])
|
|
79
103
|
|
|
80
104
|
|
|
81
|
-
def base2(n) -> str:
|
|
105
|
+
def base2(n: float) -> str:
|
|
106
|
+
"""Deprecated function to convert a number to a human readable string using base 2 units.
|
|
82
107
|
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
n : float
|
|
111
|
+
The number to convert
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
str
|
|
116
|
+
A human readable string
|
|
117
|
+
"""
|
|
83
118
|
warnings.warn(
|
|
84
119
|
"Function base2 is deprecated and will be removed in a future version. Use base2_to_human instead.",
|
|
85
120
|
category=DeprecationWarning,
|
|
@@ -97,15 +132,27 @@ PERIODS = (
|
|
|
97
132
|
)
|
|
98
133
|
|
|
99
134
|
|
|
100
|
-
def _plural(count):
|
|
135
|
+
def _plural(count: int) -> str:
|
|
136
|
+
"""Return 's' if count is not 1, otherwise return an empty string.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
count : int
|
|
141
|
+
The count
|
|
142
|
+
|
|
143
|
+
Returns
|
|
144
|
+
-------
|
|
145
|
+
str
|
|
146
|
+
's' if count is not 1, otherwise an empty string
|
|
147
|
+
"""
|
|
101
148
|
if count != 1:
|
|
102
149
|
return "s"
|
|
103
150
|
else:
|
|
104
151
|
return ""
|
|
105
152
|
|
|
106
153
|
|
|
107
|
-
def seconds_to_human(seconds: float) -> str:
|
|
108
|
-
"""Convert a number of seconds to a human readable string
|
|
154
|
+
def seconds_to_human(seconds: Union[float, datetime.timedelta]) -> str:
|
|
155
|
+
"""Convert a number of seconds to a human readable string.
|
|
109
156
|
|
|
110
157
|
>>> seconds_to_human(4000)
|
|
111
158
|
'1 hour 6 minutes 40 seconds'
|
|
@@ -119,7 +166,6 @@ def seconds_to_human(seconds: float) -> str:
|
|
|
119
166
|
-------
|
|
120
167
|
str
|
|
121
168
|
A human readable string
|
|
122
|
-
|
|
123
169
|
"""
|
|
124
170
|
if isinstance(seconds, datetime.timedelta):
|
|
125
171
|
seconds = seconds.total_seconds()
|
|
@@ -164,6 +210,18 @@ def seconds_to_human(seconds: float) -> str:
|
|
|
164
210
|
|
|
165
211
|
|
|
166
212
|
def seconds(seconds: float) -> str:
|
|
213
|
+
"""Deprecated function to convert seconds to a human readable string.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
seconds : float
|
|
218
|
+
The number of seconds
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
str
|
|
223
|
+
A human readable string
|
|
224
|
+
"""
|
|
167
225
|
warnings.warn(
|
|
168
226
|
"Function seconds is deprecated and will be removed in a future version. Use seconds_to_human instead.",
|
|
169
227
|
category=DeprecationWarning,
|
|
@@ -172,7 +230,21 @@ def seconds(seconds: float) -> str:
|
|
|
172
230
|
return seconds_to_human(seconds)
|
|
173
231
|
|
|
174
232
|
|
|
175
|
-
def plural(value, what):
|
|
233
|
+
def plural(value: int, what: str) -> str:
|
|
234
|
+
"""Return a string with the value and the pluralized form of what.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
value : int
|
|
239
|
+
The value
|
|
240
|
+
what : str
|
|
241
|
+
The string to pluralize
|
|
242
|
+
|
|
243
|
+
Returns
|
|
244
|
+
-------
|
|
245
|
+
str
|
|
246
|
+
The value and the pluralized form of what
|
|
247
|
+
"""
|
|
176
248
|
return f"{value:,} {what}{_plural(value)}"
|
|
177
249
|
|
|
178
250
|
|
|
@@ -202,7 +274,19 @@ MONTH = [
|
|
|
202
274
|
]
|
|
203
275
|
|
|
204
276
|
|
|
205
|
-
def __(n):
|
|
277
|
+
def __(n: int) -> str:
|
|
278
|
+
"""Return the ordinal suffix for a number.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
n : int
|
|
283
|
+
The number
|
|
284
|
+
|
|
285
|
+
Returns
|
|
286
|
+
-------
|
|
287
|
+
str
|
|
288
|
+
The ordinal suffix
|
|
289
|
+
"""
|
|
206
290
|
if n in (11, 12, 13):
|
|
207
291
|
return "th"
|
|
208
292
|
|
|
@@ -218,8 +302,10 @@ def __(n):
|
|
|
218
302
|
return "th"
|
|
219
303
|
|
|
220
304
|
|
|
221
|
-
def when(
|
|
222
|
-
|
|
305
|
+
def when(
|
|
306
|
+
then: datetime.datetime, now: Optional[datetime.datetime] = None, short: bool = True, use_utc: bool = False
|
|
307
|
+
) -> str:
|
|
308
|
+
"""Generate a human readable string for a date, relative to now.
|
|
223
309
|
|
|
224
310
|
>>> when(datetime.datetime.now() - datetime.timedelta(hours=2))
|
|
225
311
|
'2 hours ago'
|
|
@@ -243,7 +329,7 @@ def when(then, now=None, short=True, use_utc=False) -> str:
|
|
|
243
329
|
now : datetime.datetime, optional
|
|
244
330
|
The reference date, by default NOW
|
|
245
331
|
short : bool, optional
|
|
246
|
-
|
|
332
|
+
Generate shorter strings, by default True
|
|
247
333
|
use_utc : bool, optional
|
|
248
334
|
Use UTC time, by default False
|
|
249
335
|
|
|
@@ -251,7 +337,6 @@ def when(then, now=None, short=True, use_utc=False) -> str:
|
|
|
251
337
|
-------
|
|
252
338
|
str
|
|
253
339
|
A human readable string
|
|
254
|
-
|
|
255
340
|
"""
|
|
256
341
|
last = "last"
|
|
257
342
|
|
|
@@ -344,7 +429,21 @@ def when(then, now=None, short=True, use_utc=False) -> str:
|
|
|
344
429
|
)
|
|
345
430
|
|
|
346
431
|
|
|
347
|
-
def string_distance(s, t):
|
|
432
|
+
def string_distance(s: str, t: str) -> int:
|
|
433
|
+
"""Calculate the Levenshtein distance between two strings.
|
|
434
|
+
|
|
435
|
+
Parameters
|
|
436
|
+
----------
|
|
437
|
+
s : str
|
|
438
|
+
The first string
|
|
439
|
+
t : str
|
|
440
|
+
The second string
|
|
441
|
+
|
|
442
|
+
Returns
|
|
443
|
+
-------
|
|
444
|
+
int
|
|
445
|
+
The Levenshtein distance
|
|
446
|
+
"""
|
|
348
447
|
import numpy as np
|
|
349
448
|
|
|
350
449
|
m = len(s)
|
|
@@ -369,8 +468,8 @@ def string_distance(s, t):
|
|
|
369
468
|
return d[m, n]
|
|
370
469
|
|
|
371
470
|
|
|
372
|
-
def did_you_mean(word, vocabulary) -> str:
|
|
373
|
-
"""Pick the closest word in a vocabulary
|
|
471
|
+
def did_you_mean(word: str, vocabulary: List[str]) -> str:
|
|
472
|
+
"""Pick the closest word in a vocabulary.
|
|
374
473
|
|
|
375
474
|
>>> did_you_mean("aple", ["banana", "lemon", "apple", "orange"])
|
|
376
475
|
'apple'
|
|
@@ -379,7 +478,7 @@ def did_you_mean(word, vocabulary) -> str:
|
|
|
379
478
|
----------
|
|
380
479
|
word : str
|
|
381
480
|
The word to look for
|
|
382
|
-
vocabulary : list of
|
|
481
|
+
vocabulary : list of str
|
|
383
482
|
The list of known words
|
|
384
483
|
|
|
385
484
|
Returns
|
|
@@ -392,14 +491,26 @@ def did_you_mean(word, vocabulary) -> str:
|
|
|
392
491
|
return best
|
|
393
492
|
|
|
394
493
|
|
|
395
|
-
def dict_to_human(query):
|
|
494
|
+
def dict_to_human(query: Dict[str, Any]) -> str:
|
|
495
|
+
"""Convert a dictionary to a human readable string.
|
|
496
|
+
|
|
497
|
+
Parameters
|
|
498
|
+
----------
|
|
499
|
+
query : dict
|
|
500
|
+
The dictionary to convert
|
|
501
|
+
|
|
502
|
+
Returns
|
|
503
|
+
-------
|
|
504
|
+
str
|
|
505
|
+
A human readable string
|
|
506
|
+
"""
|
|
396
507
|
lst = [f"{k}={v}" for k, v in sorted(query.items())]
|
|
397
508
|
|
|
398
509
|
return list_to_human(lst)
|
|
399
510
|
|
|
400
511
|
|
|
401
|
-
def list_to_human(lst, conjunction="and") -> str:
|
|
402
|
-
"""Convert a list of strings to a human readable string
|
|
512
|
+
def list_to_human(lst: List[str], conjunction: str = "and") -> str:
|
|
513
|
+
"""Convert a list of strings to a human readable string.
|
|
403
514
|
|
|
404
515
|
>>> list_to_human(["banana", "lemon", "apple", "orange"])
|
|
405
516
|
'banana, lemon, apple and orange'
|
|
@@ -425,7 +536,25 @@ def list_to_human(lst, conjunction="and") -> str:
|
|
|
425
536
|
return f" {conjunction} ".join(lst)
|
|
426
537
|
|
|
427
538
|
|
|
428
|
-
def human_to_number(value, name, units, none_ok):
|
|
539
|
+
def human_to_number(value: Union[str, int], name: str, units: Dict[str, int], none_ok: bool) -> Optional[int]:
|
|
540
|
+
"""Convert a human readable string to a number.
|
|
541
|
+
|
|
542
|
+
Parameters
|
|
543
|
+
----------
|
|
544
|
+
value : str or int
|
|
545
|
+
The value to convert
|
|
546
|
+
name : str
|
|
547
|
+
The name of the value
|
|
548
|
+
units : dict
|
|
549
|
+
The units to use for conversion
|
|
550
|
+
none_ok : bool
|
|
551
|
+
Whether None is an acceptable value
|
|
552
|
+
|
|
553
|
+
Returns
|
|
554
|
+
-------
|
|
555
|
+
int or None
|
|
556
|
+
The converted value
|
|
557
|
+
"""
|
|
429
558
|
if value is None and none_ok:
|
|
430
559
|
return None
|
|
431
560
|
|
|
@@ -444,7 +573,27 @@ def human_to_number(value, name, units, none_ok):
|
|
|
444
573
|
return value * units[unit]
|
|
445
574
|
|
|
446
575
|
|
|
447
|
-
def as_number(
|
|
576
|
+
def as_number(
|
|
577
|
+
value: Union[str, int], name: Optional[str] = None, units: Optional[Dict[str, int]] = None, none_ok: bool = False
|
|
578
|
+
) -> Optional[int]:
|
|
579
|
+
"""Deprecated function to convert a human readable string to a number.
|
|
580
|
+
|
|
581
|
+
Parameters
|
|
582
|
+
----------
|
|
583
|
+
value : str or int
|
|
584
|
+
The value to convert
|
|
585
|
+
name : str, optional
|
|
586
|
+
The name of the value
|
|
587
|
+
units : dict, optional
|
|
588
|
+
The units to use for conversion
|
|
589
|
+
none_ok : bool, optional
|
|
590
|
+
Whether None is an acceptable value
|
|
591
|
+
|
|
592
|
+
Returns
|
|
593
|
+
-------
|
|
594
|
+
int or None
|
|
595
|
+
The converted value
|
|
596
|
+
"""
|
|
448
597
|
warnings.warn(
|
|
449
598
|
"Function as_number is deprecated and will be removed in a future version. Use human_to_number instead.",
|
|
450
599
|
category=DeprecationWarning,
|
|
@@ -453,12 +602,44 @@ def as_number(value, name=None, units=None, none_ok=False):
|
|
|
453
602
|
return human_to_number(value, name, units, none_ok)
|
|
454
603
|
|
|
455
604
|
|
|
456
|
-
def human_seconds(value, name=None, none_ok=False):
|
|
605
|
+
def human_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
606
|
+
"""Convert a human readable string to seconds.
|
|
607
|
+
|
|
608
|
+
Parameters
|
|
609
|
+
----------
|
|
610
|
+
value : str or int
|
|
611
|
+
The value to convert
|
|
612
|
+
name : str, optional
|
|
613
|
+
The name of the value
|
|
614
|
+
none_ok : bool, optional
|
|
615
|
+
Whether None is an acceptable value
|
|
616
|
+
|
|
617
|
+
Returns
|
|
618
|
+
-------
|
|
619
|
+
int or None
|
|
620
|
+
The converted value in seconds
|
|
621
|
+
"""
|
|
457
622
|
units = dict(s=1, m=60, h=3600, d=86400, w=86400 * 7)
|
|
458
623
|
return human_to_number(value, name, units, none_ok)
|
|
459
624
|
|
|
460
625
|
|
|
461
|
-
def as_seconds(value, name=None, none_ok=False):
|
|
626
|
+
def as_seconds(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
627
|
+
"""Deprecated function to convert a human readable string to seconds.
|
|
628
|
+
|
|
629
|
+
Parameters
|
|
630
|
+
----------
|
|
631
|
+
value : str or int
|
|
632
|
+
The value to convert
|
|
633
|
+
name : str, optional
|
|
634
|
+
The name of the value
|
|
635
|
+
none_ok : bool, optional
|
|
636
|
+
Whether None is an acceptable value
|
|
637
|
+
|
|
638
|
+
Returns
|
|
639
|
+
-------
|
|
640
|
+
int or None
|
|
641
|
+
The converted value in seconds
|
|
642
|
+
"""
|
|
462
643
|
warnings.warn(
|
|
463
644
|
"Function as_seconds is deprecated and will be removed in a future version. Use human_seconds instead.",
|
|
464
645
|
category=DeprecationWarning,
|
|
@@ -467,12 +648,44 @@ def as_seconds(value, name=None, none_ok=False):
|
|
|
467
648
|
return human_seconds(value, name, none_ok)
|
|
468
649
|
|
|
469
650
|
|
|
470
|
-
def human_to_percent(value, name=None, none_ok=False):
|
|
651
|
+
def human_to_percent(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
652
|
+
"""Convert a human readable string to a percentage.
|
|
653
|
+
|
|
654
|
+
Parameters
|
|
655
|
+
----------
|
|
656
|
+
value : str or int
|
|
657
|
+
The value to convert
|
|
658
|
+
name : str, optional
|
|
659
|
+
The name of the value
|
|
660
|
+
none_ok : bool, optional
|
|
661
|
+
Whether None is an acceptable value
|
|
662
|
+
|
|
663
|
+
Returns
|
|
664
|
+
-------
|
|
665
|
+
int or None
|
|
666
|
+
The converted value in percentage
|
|
667
|
+
"""
|
|
471
668
|
units = {"%": 1}
|
|
472
669
|
return human_to_number(value, name, units, none_ok)
|
|
473
670
|
|
|
474
671
|
|
|
475
|
-
def as_percent(value, name=None, none_ok=False):
|
|
672
|
+
def as_percent(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
673
|
+
"""Deprecated function to convert a human readable string to a percentage.
|
|
674
|
+
|
|
675
|
+
Parameters
|
|
676
|
+
----------
|
|
677
|
+
value : str or int
|
|
678
|
+
The value to convert
|
|
679
|
+
name : str, optional
|
|
680
|
+
The name of the value
|
|
681
|
+
none_ok : bool, optional
|
|
682
|
+
Whether None is an acceptable value
|
|
683
|
+
|
|
684
|
+
Returns
|
|
685
|
+
-------
|
|
686
|
+
int or None
|
|
687
|
+
The converted value in percentage
|
|
688
|
+
"""
|
|
476
689
|
warnings.warn(
|
|
477
690
|
"Function as_percent is deprecated and will be removed in a future version. Use human_to_percent instead.",
|
|
478
691
|
category=DeprecationWarning,
|
|
@@ -481,7 +694,23 @@ def as_percent(value, name=None, none_ok=False):
|
|
|
481
694
|
return human_to_percent(value, name, none_ok)
|
|
482
695
|
|
|
483
696
|
|
|
484
|
-
def human_to_bytes(value, name=None, none_ok=False):
|
|
697
|
+
def human_to_bytes(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
698
|
+
"""Convert a human readable string to bytes.
|
|
699
|
+
|
|
700
|
+
Parameters
|
|
701
|
+
----------
|
|
702
|
+
value : str or int
|
|
703
|
+
The value to convert
|
|
704
|
+
name : str, optional
|
|
705
|
+
The name of the value
|
|
706
|
+
none_ok : bool, optional
|
|
707
|
+
Whether None is an acceptable value
|
|
708
|
+
|
|
709
|
+
Returns
|
|
710
|
+
-------
|
|
711
|
+
int or None
|
|
712
|
+
The converted value in bytes
|
|
713
|
+
"""
|
|
485
714
|
units = {}
|
|
486
715
|
n = 1
|
|
487
716
|
for u in "KMGTP":
|
|
@@ -492,7 +721,23 @@ def human_to_bytes(value, name=None, none_ok=False):
|
|
|
492
721
|
return human_to_number(value, name, units, none_ok)
|
|
493
722
|
|
|
494
723
|
|
|
495
|
-
def as_bytes(value, name=None, none_ok=False):
|
|
724
|
+
def as_bytes(value: Union[str, int], name: Optional[str] = None, none_ok: bool = False) -> Optional[int]:
|
|
725
|
+
"""Deprecated function to convert a human readable string to bytes.
|
|
726
|
+
|
|
727
|
+
Parameters
|
|
728
|
+
----------
|
|
729
|
+
value : str or int
|
|
730
|
+
The value to convert
|
|
731
|
+
name : str, optional
|
|
732
|
+
The name of the value
|
|
733
|
+
none_ok : bool, optional
|
|
734
|
+
Whether None is an acceptable value
|
|
735
|
+
|
|
736
|
+
Returns
|
|
737
|
+
-------
|
|
738
|
+
int or None
|
|
739
|
+
The converted value in bytes
|
|
740
|
+
"""
|
|
496
741
|
warnings.warn(
|
|
497
742
|
"Function as_bytes is deprecated and will be removed in a future version. Use human_to_bytes instead.",
|
|
498
743
|
category=DeprecationWarning,
|
|
@@ -501,7 +746,23 @@ def as_bytes(value, name=None, none_ok=False):
|
|
|
501
746
|
return human_to_bytes(value, name, none_ok)
|
|
502
747
|
|
|
503
748
|
|
|
504
|
-
def human_to_timedelta(value, name=None, none_ok=False):
|
|
749
|
+
def human_to_timedelta(value: str, name: Optional[str] = None, none_ok: bool = False) -> datetime.timedelta:
|
|
750
|
+
"""Convert a human readable string to a timedelta.
|
|
751
|
+
|
|
752
|
+
Parameters
|
|
753
|
+
----------
|
|
754
|
+
value : str
|
|
755
|
+
The value to convert
|
|
756
|
+
name : str, optional
|
|
757
|
+
The name of the value
|
|
758
|
+
none_ok : bool, optional
|
|
759
|
+
Whether None is an acceptable value
|
|
760
|
+
|
|
761
|
+
Returns
|
|
762
|
+
-------
|
|
763
|
+
datetime.timedelta
|
|
764
|
+
The converted value as a timedelta
|
|
765
|
+
"""
|
|
505
766
|
if value is None and none_ok:
|
|
506
767
|
return None
|
|
507
768
|
|
|
@@ -537,7 +798,23 @@ def human_to_timedelta(value, name=None, none_ok=False):
|
|
|
537
798
|
)
|
|
538
799
|
|
|
539
800
|
|
|
540
|
-
def as_timedelta(value, name=None, none_ok=False):
|
|
801
|
+
def as_timedelta(value: str, name: Optional[str] = None, none_ok: bool = False) -> datetime.timedelta:
|
|
802
|
+
"""Deprecated function to convert a human readable string to a timedelta.
|
|
803
|
+
|
|
804
|
+
Parameters
|
|
805
|
+
----------
|
|
806
|
+
value : str
|
|
807
|
+
The value to convert
|
|
808
|
+
name : str, optional
|
|
809
|
+
The name of the value
|
|
810
|
+
none_ok : bool, optional
|
|
811
|
+
Whether None is an acceptable value
|
|
812
|
+
|
|
813
|
+
Returns
|
|
814
|
+
-------
|
|
815
|
+
datetime.timedelta
|
|
816
|
+
The converted value as a timedelta
|
|
817
|
+
"""
|
|
541
818
|
warnings.warn(
|
|
542
819
|
"Function as_timedelta is deprecated and will be removed in a future version. Use human_to_timedelta instead.",
|
|
543
820
|
category=DeprecationWarning,
|
|
@@ -546,14 +823,26 @@ def as_timedelta(value, name=None, none_ok=False):
|
|
|
546
823
|
return human_to_timedelta(value, name, none_ok)
|
|
547
824
|
|
|
548
825
|
|
|
549
|
-
def rounded_datetime(d):
|
|
826
|
+
def rounded_datetime(d: datetime.datetime) -> datetime.datetime:
|
|
827
|
+
"""Round a datetime to the nearest second.
|
|
828
|
+
|
|
829
|
+
Parameters
|
|
830
|
+
----------
|
|
831
|
+
d : datetime.datetime
|
|
832
|
+
The datetime to round
|
|
833
|
+
|
|
834
|
+
Returns
|
|
835
|
+
-------
|
|
836
|
+
datetime.datetime
|
|
837
|
+
The rounded datetime
|
|
838
|
+
"""
|
|
550
839
|
if float(d.microsecond) / 1000.0 / 1000.0 >= 0.5:
|
|
551
840
|
d = d + datetime.timedelta(seconds=1)
|
|
552
841
|
d = d.replace(microsecond=0)
|
|
553
842
|
return d
|
|
554
843
|
|
|
555
844
|
|
|
556
|
-
def json_pretty_dump(obj, max_line_length=120, default=str) -> str:
|
|
845
|
+
def json_pretty_dump(obj: Any, max_line_length: int = 120, default: Callable = str) -> str:
|
|
557
846
|
"""Custom JSON dump function that keeps dicts and lists on one line if they are short enough.
|
|
558
847
|
|
|
559
848
|
Parameters
|
|
@@ -571,7 +860,7 @@ def json_pretty_dump(obj, max_line_length=120, default=str) -> str:
|
|
|
571
860
|
JSON string.
|
|
572
861
|
"""
|
|
573
862
|
|
|
574
|
-
def _format_json(obj, indent_level=0):
|
|
863
|
+
def _format_json(obj: Any, indent_level: int = 0) -> str:
|
|
575
864
|
"""Helper function to format JSON objects with custom pretty-print rules.
|
|
576
865
|
|
|
577
866
|
Parameters
|
|
@@ -609,19 +898,19 @@ def json_pretty_dump(obj, max_line_length=120, default=str) -> str:
|
|
|
609
898
|
return _format_json(obj)
|
|
610
899
|
|
|
611
900
|
|
|
612
|
-
def shorten_list(lst, max_length=5) ->
|
|
901
|
+
def shorten_list(lst: Union[List[Any], Tuple[Any]], max_length: int = 5) -> Union[List[Any], Tuple[Any]]:
|
|
613
902
|
"""Shorten a list to a maximum length.
|
|
614
903
|
|
|
615
904
|
Parameters
|
|
616
905
|
----------
|
|
617
|
-
lst : list
|
|
906
|
+
lst : list or tuple
|
|
618
907
|
The list to be shortened.
|
|
619
908
|
max_length : int, optional
|
|
620
909
|
Maximum length of the shortened list. Default is 5.
|
|
621
910
|
|
|
622
911
|
Returns
|
|
623
912
|
-------
|
|
624
|
-
list
|
|
913
|
+
list or tuple
|
|
625
914
|
Shortened list.
|
|
626
915
|
"""
|
|
627
916
|
if len(lst) <= max_length:
|
|
@@ -634,7 +923,23 @@ def shorten_list(lst, max_length=5) -> list:
|
|
|
634
923
|
return result
|
|
635
924
|
|
|
636
925
|
|
|
637
|
-
def _compress_dates(
|
|
926
|
+
def _compress_dates(
|
|
927
|
+
dates: List[datetime.datetime],
|
|
928
|
+
) -> Generator[
|
|
929
|
+
Union[List[datetime.datetime], Tuple[datetime.datetime, datetime.datetime, datetime.timedelta]], None, None
|
|
930
|
+
]:
|
|
931
|
+
"""Compress a list of dates into a more compact representation.
|
|
932
|
+
|
|
933
|
+
Parameters
|
|
934
|
+
----------
|
|
935
|
+
dates : list of datetime.datetime
|
|
936
|
+
The list of dates to compress
|
|
937
|
+
|
|
938
|
+
Returns
|
|
939
|
+
-------
|
|
940
|
+
list or tuple
|
|
941
|
+
The compressed dates
|
|
942
|
+
"""
|
|
638
943
|
dates = sorted(dates)
|
|
639
944
|
if len(dates) < 3:
|
|
640
945
|
yield dates
|
|
@@ -654,7 +959,7 @@ def _compress_dates(dates):
|
|
|
654
959
|
yield from _compress_dates([curr] + dates)
|
|
655
960
|
|
|
656
961
|
|
|
657
|
-
def compress_dates(dates) -> str:
|
|
962
|
+
def compress_dates(dates: List[Union[datetime.datetime, str]]) -> str:
|
|
658
963
|
"""Compress a list of dates into a human-readable format.
|
|
659
964
|
|
|
660
965
|
Parameters
|
|
@@ -680,7 +985,7 @@ def compress_dates(dates) -> str:
|
|
|
680
985
|
return result
|
|
681
986
|
|
|
682
987
|
|
|
683
|
-
def print_dates(dates) -> None:
|
|
988
|
+
def print_dates(dates: List[Union[datetime.datetime, str]]) -> None:
|
|
684
989
|
"""Print a list of dates in a human-readable format.
|
|
685
990
|
|
|
686
991
|
Parameters
|
|
@@ -691,7 +996,7 @@ def print_dates(dates) -> None:
|
|
|
691
996
|
print(compress_dates(dates))
|
|
692
997
|
|
|
693
998
|
|
|
694
|
-
def make_list_int(value) ->
|
|
999
|
+
def make_list_int(value: Union[str, List[int], Tuple[int], int]) -> List[int]:
|
|
695
1000
|
"""Convert a string like "1/2/3" or "1/to/3" or "1/to/10/by/2" to a list of integers.
|
|
696
1001
|
|
|
697
1002
|
Parameters
|