anemoi-utils 0.4.12__py3-none-any.whl → 0.4.13__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 +185 -28
- anemoi/utils/registry.py +122 -13
- 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/text.py +218 -54
- anemoi/utils/timer.py +91 -15
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.13.dist-info}/METADATA +6 -3
- anemoi_utils-0.4.13.dist-info/RECORD +37 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.13.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.13.dist-info}/LICENSE +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.13.dist-info}/entry_points.txt +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.13.dist-info}/top_level.txt +0 -0
anemoi/utils/remote/__init__.py
CHANGED
|
@@ -10,6 +10,9 @@ import logging
|
|
|
10
10
|
import os
|
|
11
11
|
import shutil
|
|
12
12
|
from abc import abstractmethod
|
|
13
|
+
from typing import Any
|
|
14
|
+
from typing import Dict
|
|
15
|
+
from typing import Iterable
|
|
13
16
|
|
|
14
17
|
import tqdm
|
|
15
18
|
|
|
@@ -18,13 +21,63 @@ from ..humanize import bytes_to_human
|
|
|
18
21
|
LOGGER = logging.getLogger(__name__)
|
|
19
22
|
|
|
20
23
|
|
|
21
|
-
def
|
|
24
|
+
def robust(call: callable, *args, maximum_tries: int = 60, retry_after: int = 60, **kwargs) -> callable:
|
|
25
|
+
"""Forwards the arguments to the multiurl robust function.
|
|
26
|
+
with default retry_after=60 and maximum_tries=60.
|
|
27
|
+
"""
|
|
28
|
+
from multiurl import robust as robust_
|
|
29
|
+
|
|
30
|
+
return robust_(call, *args, retry_after=retry_after, maximum_tries=maximum_tries, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _ignore(number_of_files: int, total_size: int, total_transferred: int, transfering: bool) -> None:
|
|
34
|
+
"""A placeholder function for progress reporting.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
number_of_files : int
|
|
39
|
+
The number of files being transferred.
|
|
40
|
+
total_size : int
|
|
41
|
+
The total size of the files being transferred.
|
|
42
|
+
total_transferred : int
|
|
43
|
+
The total size of the files transferred so far.
|
|
44
|
+
transfering : bool
|
|
45
|
+
Whether the transfer is in progress.
|
|
46
|
+
"""
|
|
22
47
|
pass
|
|
23
48
|
|
|
24
49
|
|
|
25
50
|
class Loader:
|
|
26
|
-
|
|
27
|
-
|
|
51
|
+
def transfer_folder(
|
|
52
|
+
self,
|
|
53
|
+
*,
|
|
54
|
+
source: str,
|
|
55
|
+
target: str,
|
|
56
|
+
overwrite: bool = False,
|
|
57
|
+
resume: bool = False,
|
|
58
|
+
verbosity: int = 1,
|
|
59
|
+
threads: int = 1,
|
|
60
|
+
progress: callable = None,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Transfer a folder from the source to the target location.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
source : str
|
|
67
|
+
The source folder path.
|
|
68
|
+
target : str
|
|
69
|
+
The target folder path.
|
|
70
|
+
overwrite : bool, optional
|
|
71
|
+
Whether to overwrite the target if it exists, by default False.
|
|
72
|
+
resume : bool, optional
|
|
73
|
+
Whether to resume the transfer if possible, by default False.
|
|
74
|
+
verbosity : int, optional
|
|
75
|
+
The verbosity level, by default 1.
|
|
76
|
+
threads : int, optional
|
|
77
|
+
The number of threads to use, by default 1.
|
|
78
|
+
progress : callable, optional
|
|
79
|
+
A callable for progress reporting, by default None.
|
|
80
|
+
"""
|
|
28
81
|
assert verbosity == 1, verbosity
|
|
29
82
|
|
|
30
83
|
if progress is None:
|
|
@@ -93,7 +146,48 @@ class Loader:
|
|
|
93
146
|
executor.shutdown(wait=False, cancel_futures=True)
|
|
94
147
|
raise
|
|
95
148
|
|
|
96
|
-
def transfer_file(
|
|
149
|
+
def transfer_file(
|
|
150
|
+
self,
|
|
151
|
+
source: str,
|
|
152
|
+
target: str,
|
|
153
|
+
overwrite: bool,
|
|
154
|
+
resume: bool,
|
|
155
|
+
verbosity: int,
|
|
156
|
+
threads: int = 1,
|
|
157
|
+
progress: callable = None,
|
|
158
|
+
config: dict = None,
|
|
159
|
+
) -> int:
|
|
160
|
+
"""Transfer a file from the source to the target location.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
source : str
|
|
165
|
+
The source file path.
|
|
166
|
+
target : str
|
|
167
|
+
The target file path.
|
|
168
|
+
overwrite : bool
|
|
169
|
+
Whether to overwrite the target if it exists.
|
|
170
|
+
resume : bool
|
|
171
|
+
Whether to resume the transfer if possible.
|
|
172
|
+
verbosity : int
|
|
173
|
+
The verbosity level.
|
|
174
|
+
threads : int, optional
|
|
175
|
+
The number of threads to use, by default 1.
|
|
176
|
+
progress : callable, optional
|
|
177
|
+
A callable for progress reporting, by default None.
|
|
178
|
+
config : dict, optional
|
|
179
|
+
Additional configuration options, by default None.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
int
|
|
184
|
+
The size of the transferred file.
|
|
185
|
+
|
|
186
|
+
Raises
|
|
187
|
+
------
|
|
188
|
+
Exception
|
|
189
|
+
If an error occurs during the transfer.
|
|
190
|
+
"""
|
|
97
191
|
try:
|
|
98
192
|
return self._transfer_file(source, target, overwrite, resume, verbosity, threads=threads, config=config)
|
|
99
193
|
except Exception as e:
|
|
@@ -102,31 +196,119 @@ class Loader:
|
|
|
102
196
|
raise
|
|
103
197
|
|
|
104
198
|
@abstractmethod
|
|
105
|
-
def list_source(self, source):
|
|
199
|
+
def list_source(self, source: str) -> Iterable:
|
|
200
|
+
"""List the files in the source location.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
source : str
|
|
205
|
+
The source location.
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
Iterable
|
|
210
|
+
An iterable of files in the source location.
|
|
211
|
+
"""
|
|
106
212
|
raise NotImplementedError
|
|
107
213
|
|
|
108
214
|
@abstractmethod
|
|
109
|
-
def source_path(self, local_path, source):
|
|
215
|
+
def source_path(self, local_path: str, source: str) -> str:
|
|
216
|
+
"""Get the source path for a local file.
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
local_path : str
|
|
221
|
+
The local file path.
|
|
222
|
+
source : str
|
|
223
|
+
The source location.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
str
|
|
228
|
+
The source path for the local file.
|
|
229
|
+
"""
|
|
110
230
|
raise NotImplementedError
|
|
111
231
|
|
|
112
232
|
@abstractmethod
|
|
113
|
-
def target_path(self, source_path, source, target):
|
|
233
|
+
def target_path(self, source_path: str, source: str, target: str) -> str:
|
|
234
|
+
"""Get the target path for a source file.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
source_path : str
|
|
239
|
+
The source file path.
|
|
240
|
+
source : str
|
|
241
|
+
The source location.
|
|
242
|
+
target : str
|
|
243
|
+
The target location.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
str
|
|
248
|
+
The target path for the source file.
|
|
249
|
+
"""
|
|
114
250
|
raise NotImplementedError
|
|
115
251
|
|
|
116
252
|
@abstractmethod
|
|
117
|
-
def source_size(self, local_path):
|
|
253
|
+
def source_size(self, local_path: str) -> int:
|
|
254
|
+
"""Get the size of a local file.
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
local_path : str
|
|
259
|
+
The local file path.
|
|
260
|
+
|
|
261
|
+
Returns
|
|
262
|
+
-------
|
|
263
|
+
int
|
|
264
|
+
The size of the local file.
|
|
265
|
+
"""
|
|
118
266
|
raise NotImplementedError
|
|
119
267
|
|
|
120
268
|
@abstractmethod
|
|
121
|
-
def copy(self, source, target, **kwargs):
|
|
269
|
+
def copy(self, source: str, target: str, **kwargs) -> None:
|
|
270
|
+
"""Copy a file or folder from the source to the target location.
|
|
271
|
+
|
|
272
|
+
Parameters
|
|
273
|
+
----------
|
|
274
|
+
source : str
|
|
275
|
+
The source location.
|
|
276
|
+
target : str
|
|
277
|
+
The target location.
|
|
278
|
+
kwargs : dict
|
|
279
|
+
Additional arguments for the transfer.
|
|
280
|
+
"""
|
|
122
281
|
raise NotImplementedError
|
|
123
282
|
|
|
124
283
|
@abstractmethod
|
|
125
|
-
def get_temporary_target(self, target, pattern):
|
|
284
|
+
def get_temporary_target(self, target: str, pattern: str) -> str:
|
|
285
|
+
"""Get a temporary target path based on the given pattern.
|
|
286
|
+
|
|
287
|
+
Parameters
|
|
288
|
+
----------
|
|
289
|
+
target : str
|
|
290
|
+
The original target path.
|
|
291
|
+
pattern : str
|
|
292
|
+
The pattern to format the temporary path.
|
|
293
|
+
|
|
294
|
+
Returns
|
|
295
|
+
-------
|
|
296
|
+
str
|
|
297
|
+
The temporary target path.
|
|
298
|
+
"""
|
|
126
299
|
raise NotImplementedError
|
|
127
300
|
|
|
128
301
|
@abstractmethod
|
|
129
|
-
def rename_target(self, target, temporary_target):
|
|
302
|
+
def rename_target(self, target: str, temporary_target: str) -> None:
|
|
303
|
+
"""Rename the target to a new target path.
|
|
304
|
+
|
|
305
|
+
Parameters
|
|
306
|
+
----------
|
|
307
|
+
target : str
|
|
308
|
+
The original target path.
|
|
309
|
+
temporary_target : str
|
|
310
|
+
The new target path.
|
|
311
|
+
"""
|
|
130
312
|
raise NotImplementedError
|
|
131
313
|
|
|
132
314
|
|
|
@@ -134,19 +316,60 @@ class BaseDownload(Loader):
|
|
|
134
316
|
action = "Downloading"
|
|
135
317
|
|
|
136
318
|
@abstractmethod
|
|
137
|
-
def copy(self, source, target, **kwargs):
|
|
319
|
+
def copy(self, source: str, target: str, **kwargs) -> None:
|
|
320
|
+
"""Copy a file or folder from the source to the target location.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
source : str
|
|
325
|
+
The source location.
|
|
326
|
+
target : str
|
|
327
|
+
The target location.
|
|
328
|
+
kwargs : dict
|
|
329
|
+
Additional arguments for the transfer.
|
|
330
|
+
"""
|
|
138
331
|
raise NotImplementedError
|
|
139
332
|
|
|
140
|
-
def get_temporary_target(self, target, pattern):
|
|
333
|
+
def get_temporary_target(self, target: str, pattern: str) -> str:
|
|
334
|
+
"""Get a temporary target path based on the given pattern.
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
target : str
|
|
339
|
+
The original target path.
|
|
340
|
+
pattern : str
|
|
341
|
+
The pattern to format the temporary path.
|
|
342
|
+
|
|
343
|
+
Returns
|
|
344
|
+
-------
|
|
345
|
+
str
|
|
346
|
+
The temporary target path.
|
|
347
|
+
"""
|
|
141
348
|
if pattern is None:
|
|
142
349
|
return target
|
|
143
350
|
dirname, basename = os.path.split(target)
|
|
144
351
|
return pattern.format(dirname=dirname, basename=basename)
|
|
145
352
|
|
|
146
|
-
def rename_target(self, target, new_target):
|
|
353
|
+
def rename_target(self, target: str, new_target: str) -> None:
|
|
354
|
+
"""Rename the target to a new target path.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
target : str
|
|
359
|
+
The original target path.
|
|
360
|
+
new_target : str
|
|
361
|
+
The new target path.
|
|
362
|
+
"""
|
|
147
363
|
os.rename(target, new_target)
|
|
148
364
|
|
|
149
|
-
def delete_target(self, target):
|
|
365
|
+
def delete_target(self, target: str) -> None:
|
|
366
|
+
"""Delete the target if it exists.
|
|
367
|
+
|
|
368
|
+
Parameters
|
|
369
|
+
----------
|
|
370
|
+
target : str
|
|
371
|
+
The target path.
|
|
372
|
+
"""
|
|
150
373
|
if os.path.exists(target):
|
|
151
374
|
shutil.rmtree(target)
|
|
152
375
|
|
|
@@ -154,26 +377,91 @@ class BaseDownload(Loader):
|
|
|
154
377
|
class BaseUpload(Loader):
|
|
155
378
|
action = "Uploading"
|
|
156
379
|
|
|
157
|
-
def copy(self, source, target, **kwargs):
|
|
380
|
+
def copy(self, source: str, target: str, **kwargs) -> None:
|
|
381
|
+
"""Copy a file or folder from the source to the target location.
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
source : str
|
|
386
|
+
The source location.
|
|
387
|
+
target : str
|
|
388
|
+
The target location.
|
|
389
|
+
kwargs : dict
|
|
390
|
+
Additional arguments for the transfer.
|
|
391
|
+
"""
|
|
158
392
|
if os.path.isdir(source):
|
|
159
393
|
self.transfer_folder(source=source, target=target, **kwargs)
|
|
160
394
|
else:
|
|
161
395
|
self.transfer_file(source=source, target=target, **kwargs)
|
|
162
396
|
|
|
163
|
-
def list_source(self, source):
|
|
397
|
+
def list_source(self, source: str) -> Iterable:
|
|
398
|
+
"""List the files in the source location.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
source : str
|
|
403
|
+
The source location.
|
|
404
|
+
|
|
405
|
+
Returns
|
|
406
|
+
-------
|
|
407
|
+
Iterable
|
|
408
|
+
An iterable of files in the source location.
|
|
409
|
+
"""
|
|
164
410
|
for root, _, files in os.walk(source):
|
|
165
411
|
for file in files:
|
|
166
412
|
yield os.path.join(root, file)
|
|
167
413
|
|
|
168
|
-
def source_path(self, local_path, source):
|
|
414
|
+
def source_path(self, local_path: str, source: str) -> str:
|
|
415
|
+
"""Get the source path for a local file.
|
|
416
|
+
|
|
417
|
+
Parameters
|
|
418
|
+
----------
|
|
419
|
+
local_path : str
|
|
420
|
+
The local file path.
|
|
421
|
+
source : str
|
|
422
|
+
The source location.
|
|
423
|
+
|
|
424
|
+
Returns
|
|
425
|
+
-------
|
|
426
|
+
str
|
|
427
|
+
The source path for the local file.
|
|
428
|
+
"""
|
|
169
429
|
return local_path
|
|
170
430
|
|
|
171
|
-
def target_path(self, source_path, source, target):
|
|
431
|
+
def target_path(self, source_path: str, source: str, target: str) -> str:
|
|
432
|
+
"""Get the target path for a source file.
|
|
433
|
+
|
|
434
|
+
Parameters
|
|
435
|
+
----------
|
|
436
|
+
source_path : str
|
|
437
|
+
The source file path.
|
|
438
|
+
source : str
|
|
439
|
+
The source location.
|
|
440
|
+
target : str
|
|
441
|
+
The target location.
|
|
442
|
+
|
|
443
|
+
Returns
|
|
444
|
+
-------
|
|
445
|
+
str
|
|
446
|
+
The target path for the source file.
|
|
447
|
+
"""
|
|
172
448
|
relative_path = os.path.relpath(source_path, source)
|
|
173
449
|
path = os.path.join(target, relative_path)
|
|
174
450
|
return path
|
|
175
451
|
|
|
176
|
-
def source_size(self, local_path):
|
|
452
|
+
def source_size(self, local_path: str) -> int:
|
|
453
|
+
"""Get the size of a local file.
|
|
454
|
+
|
|
455
|
+
Parameters
|
|
456
|
+
----------
|
|
457
|
+
local_path : str
|
|
458
|
+
The local file path.
|
|
459
|
+
|
|
460
|
+
Returns
|
|
461
|
+
-------
|
|
462
|
+
int
|
|
463
|
+
The size of the local file.
|
|
464
|
+
"""
|
|
177
465
|
return os.path.getsize(local_path)
|
|
178
466
|
|
|
179
467
|
|
|
@@ -188,21 +476,22 @@ class Transfer:
|
|
|
188
476
|
|
|
189
477
|
def __init__(
|
|
190
478
|
self,
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
479
|
+
*,
|
|
480
|
+
source: str,
|
|
481
|
+
target: str,
|
|
482
|
+
overwrite: bool = False,
|
|
483
|
+
resume: bool = False,
|
|
484
|
+
verbosity: int = 1,
|
|
485
|
+
threads: int = 1,
|
|
486
|
+
progress: callable = None,
|
|
487
|
+
temporary_target: bool = False,
|
|
199
488
|
):
|
|
200
489
|
if target == ".":
|
|
201
490
|
target = os.path.basename(source)
|
|
202
491
|
if not target:
|
|
203
492
|
target = os.path.basename(os.path.dirname(source))
|
|
204
493
|
|
|
205
|
-
temporary_target = {
|
|
494
|
+
temporary_target: Dict[Any, Any] = {
|
|
206
495
|
False: None,
|
|
207
496
|
True: "{dirname}-downloading/{basename}",
|
|
208
497
|
"-tmp/*": "{dirname}-tmp/{basename}",
|
|
@@ -223,8 +512,14 @@ class Transfer:
|
|
|
223
512
|
cls = _find_transfer_class(self.source, self.target)
|
|
224
513
|
self.loader = cls()
|
|
225
514
|
|
|
226
|
-
def run(self):
|
|
515
|
+
def run(self) -> "Transfer":
|
|
516
|
+
"""Execute the transfer process.
|
|
227
517
|
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
Transfer
|
|
521
|
+
The Transfer instance.
|
|
522
|
+
"""
|
|
228
523
|
target = self.loader.get_temporary_target(self.target, self.temporary_target)
|
|
229
524
|
if target != self.target:
|
|
230
525
|
LOGGER.info(f"Using temporary target {target} to copy to {self.target}")
|
|
@@ -256,16 +551,51 @@ class Transfer:
|
|
|
256
551
|
|
|
257
552
|
return self
|
|
258
553
|
|
|
259
|
-
def rename_target(self, target, new_target):
|
|
554
|
+
def rename_target(self, target: str, new_target: str) -> None:
|
|
555
|
+
"""Rename the target to a new target path.
|
|
556
|
+
|
|
557
|
+
Parameters
|
|
558
|
+
----------
|
|
559
|
+
target : str
|
|
560
|
+
The original target path.
|
|
561
|
+
new_target : str
|
|
562
|
+
The new target path.
|
|
563
|
+
"""
|
|
260
564
|
if target != new_target:
|
|
261
565
|
LOGGER.info(f"Renaming temporary target {target} into {self.target}")
|
|
262
566
|
return self.loader.rename_target(target, new_target)
|
|
263
567
|
|
|
264
|
-
def delete_target(self, target):
|
|
568
|
+
def delete_target(self, target: str) -> None:
|
|
569
|
+
"""Delete the target if it exists.
|
|
570
|
+
|
|
571
|
+
Parameters
|
|
572
|
+
----------
|
|
573
|
+
target : str
|
|
574
|
+
The target path.
|
|
575
|
+
"""
|
|
265
576
|
return self.loader.delete_target(target)
|
|
266
577
|
|
|
267
578
|
|
|
268
|
-
def _find_transfer_class(source, target):
|
|
579
|
+
def _find_transfer_class(source: str, target: str) -> type:
|
|
580
|
+
"""Find the appropriate transfer class based on the source and target locations.
|
|
581
|
+
|
|
582
|
+
Parameters
|
|
583
|
+
----------
|
|
584
|
+
source : str
|
|
585
|
+
The source location.
|
|
586
|
+
target : str
|
|
587
|
+
The target location.
|
|
588
|
+
|
|
589
|
+
Returns
|
|
590
|
+
-------
|
|
591
|
+
type
|
|
592
|
+
The transfer class.
|
|
593
|
+
|
|
594
|
+
Raises
|
|
595
|
+
------
|
|
596
|
+
TransferMethodNotImplementedError
|
|
597
|
+
If the transfer method is not implemented.
|
|
598
|
+
"""
|
|
269
599
|
from_ssh = source.startswith("ssh://")
|
|
270
600
|
into_ssh = target.startswith("ssh://")
|
|
271
601
|
|
|
@@ -298,8 +628,12 @@ def _find_transfer_class(source, target):
|
|
|
298
628
|
|
|
299
629
|
|
|
300
630
|
# this is the public API
|
|
301
|
-
def transfer(
|
|
302
|
-
|
|
631
|
+
def transfer(
|
|
632
|
+
source, target, *, overwrite=False, resume=False, verbosity=1, progress=None, threads=1, temporary_target=False
|
|
633
|
+
) -> Loader:
|
|
634
|
+
"""Transfer files or folders from the source to the target location.
|
|
635
|
+
|
|
636
|
+
Parameters
|
|
303
637
|
----------
|
|
304
638
|
source : str
|
|
305
639
|
A path to a local file or folder or a URL to a file or a folder on S3.
|
|
@@ -316,7 +650,7 @@ def transfer(*args, **kwargs) -> Loader:
|
|
|
316
650
|
By default False
|
|
317
651
|
verbosity : int, optional
|
|
318
652
|
The level of verbosity, by default 1
|
|
319
|
-
progress: callable, optional
|
|
653
|
+
progress : callable, optional
|
|
320
654
|
A callable that will be called with the number of files, the total size of the files, the total size
|
|
321
655
|
transferred and a boolean indicating if the transfer has started. By default None
|
|
322
656
|
threads : int, optional
|
|
@@ -325,8 +659,22 @@ def transfer(*args, **kwargs) -> Loader:
|
|
|
325
659
|
Experimental feature
|
|
326
660
|
If True and if the target location supports it, the data will be uploaded to a temporary location
|
|
327
661
|
then renamed to the final location. Supported by SSH and local targets, not supported by S3.
|
|
328
|
-
By default False
|
|
662
|
+
By default False.
|
|
663
|
+
|
|
664
|
+
Returns
|
|
665
|
+
-------
|
|
666
|
+
Loader
|
|
667
|
+
The Loader instance.
|
|
329
668
|
"""
|
|
330
|
-
copier = Transfer(
|
|
669
|
+
copier = Transfer(
|
|
670
|
+
source=source,
|
|
671
|
+
target=target,
|
|
672
|
+
overwrite=overwrite,
|
|
673
|
+
resume=resume,
|
|
674
|
+
verbosity=verbosity,
|
|
675
|
+
progress=progress,
|
|
676
|
+
threads=threads,
|
|
677
|
+
temporary_target=temporary_target,
|
|
678
|
+
)
|
|
331
679
|
copier.run()
|
|
332
680
|
return copier
|