megfile 4.2.5__py3-none-any.whl → 5.0.0__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.
- megfile/__init__.py +13 -293
- megfile/cli.py +37 -20
- megfile/config.py +10 -1
- megfile/errors.py +2 -2
- megfile/fs_path.py +32 -3
- megfile/interfaces.py +21 -10
- megfile/lib/base_memory_handler.py +92 -0
- megfile/lib/glob.py +3 -3
- megfile/lib/http_prefetch_reader.py +22 -22
- megfile/lib/s3_memory_handler.py +14 -81
- megfile/lib/webdav_memory_handler.py +83 -0
- megfile/lib/webdav_prefetch_reader.py +115 -0
- megfile/pathlike.py +3 -4
- megfile/s3_path.py +40 -32
- megfile/sftp2_path.py +38 -62
- megfile/sftp_path.py +238 -1
- megfile/smart.py +70 -29
- megfile/smart_path.py +181 -85
- megfile/version.py +1 -1
- megfile/webdav_path.py +159 -165
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/METADATA +27 -39
- megfile-5.0.0.dist-info/RECORD +51 -0
- megfile/fs.py +0 -627
- megfile/hdfs.py +0 -408
- megfile/http.py +0 -114
- megfile/s3.py +0 -540
- megfile/sftp.py +0 -821
- megfile/sftp2.py +0 -827
- megfile/stdio.py +0 -30
- megfile/webdav.py +0 -552
- megfile-4.2.5.dist-info/RECORD +0 -56
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/WHEEL +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/entry_points.txt +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/licenses/LICENSE +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/licenses/LICENSE.pyre +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.0.dist-info}/top_level.txt +0 -0
megfile/__init__.py
CHANGED
|
@@ -1,164 +1,17 @@
|
|
|
1
|
-
from megfile.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
fs_expanduser,
|
|
7
|
-
fs_getmd5,
|
|
8
|
-
fs_getmtime,
|
|
9
|
-
fs_getsize,
|
|
10
|
-
fs_glob,
|
|
11
|
-
fs_glob_stat,
|
|
12
|
-
fs_home,
|
|
13
|
-
fs_iglob,
|
|
14
|
-
fs_isabs,
|
|
15
|
-
fs_isdir,
|
|
16
|
-
fs_isfile,
|
|
17
|
-
fs_islink,
|
|
18
|
-
fs_ismount,
|
|
19
|
-
fs_listdir,
|
|
20
|
-
fs_load_from,
|
|
21
|
-
fs_lstat,
|
|
22
|
-
fs_makedirs,
|
|
23
|
-
fs_move,
|
|
24
|
-
fs_readlink,
|
|
25
|
-
fs_realpath,
|
|
26
|
-
fs_relpath,
|
|
27
|
-
fs_remove,
|
|
28
|
-
fs_rename,
|
|
29
|
-
fs_resolve,
|
|
30
|
-
fs_save_as,
|
|
31
|
-
fs_scan,
|
|
32
|
-
fs_scan_stat,
|
|
33
|
-
fs_scandir,
|
|
34
|
-
fs_stat,
|
|
35
|
-
fs_symlink,
|
|
36
|
-
fs_sync,
|
|
37
|
-
fs_unlink,
|
|
38
|
-
fs_walk,
|
|
39
|
-
is_fs,
|
|
40
|
-
)
|
|
41
|
-
from megfile.fs_path import FSPath
|
|
42
|
-
from megfile.hdfs import (
|
|
43
|
-
hdfs_exists,
|
|
44
|
-
hdfs_getmd5,
|
|
45
|
-
hdfs_getmtime,
|
|
46
|
-
hdfs_getsize,
|
|
47
|
-
hdfs_glob,
|
|
48
|
-
hdfs_glob_stat,
|
|
49
|
-
hdfs_iglob,
|
|
50
|
-
hdfs_isdir,
|
|
51
|
-
hdfs_isfile,
|
|
52
|
-
hdfs_listdir,
|
|
53
|
-
hdfs_load_from,
|
|
54
|
-
hdfs_makedirs,
|
|
55
|
-
hdfs_move,
|
|
56
|
-
hdfs_open,
|
|
57
|
-
hdfs_remove,
|
|
58
|
-
hdfs_save_as,
|
|
59
|
-
hdfs_scan,
|
|
60
|
-
hdfs_scan_stat,
|
|
61
|
-
hdfs_scandir,
|
|
62
|
-
hdfs_stat,
|
|
63
|
-
hdfs_unlink,
|
|
64
|
-
hdfs_walk,
|
|
65
|
-
is_hdfs,
|
|
66
|
-
)
|
|
67
|
-
from megfile.hdfs_path import HdfsPath
|
|
68
|
-
from megfile.http import (
|
|
69
|
-
http_exists,
|
|
70
|
-
http_getmtime,
|
|
71
|
-
http_getsize,
|
|
72
|
-
http_open,
|
|
73
|
-
http_stat,
|
|
74
|
-
is_http,
|
|
75
|
-
)
|
|
76
|
-
from megfile.http_path import HttpPath, HttpsPath
|
|
77
|
-
from megfile.s3 import (
|
|
1
|
+
from megfile.fs_path import FSPath, is_fs
|
|
2
|
+
from megfile.hdfs_path import HdfsPath, is_hdfs
|
|
3
|
+
from megfile.http_path import HttpPath, HttpsPath, is_http
|
|
4
|
+
from megfile.s3_path import (
|
|
5
|
+
S3Path,
|
|
78
6
|
is_s3,
|
|
79
|
-
s3_access,
|
|
80
7
|
s3_buffered_open,
|
|
81
8
|
s3_cached_open,
|
|
82
|
-
s3_concat,
|
|
83
|
-
s3_copy,
|
|
84
|
-
s3_download,
|
|
85
|
-
s3_exists,
|
|
86
|
-
s3_getmd5,
|
|
87
|
-
s3_getmtime,
|
|
88
|
-
s3_getsize,
|
|
89
|
-
s3_glob,
|
|
90
|
-
s3_glob_stat,
|
|
91
|
-
s3_hasbucket,
|
|
92
|
-
s3_iglob,
|
|
93
|
-
s3_isdir,
|
|
94
|
-
s3_isfile,
|
|
95
|
-
s3_listdir,
|
|
96
|
-
s3_load_content,
|
|
97
|
-
s3_load_from,
|
|
98
|
-
s3_lstat,
|
|
99
|
-
s3_makedirs,
|
|
100
9
|
s3_memory_open,
|
|
101
|
-
s3_move,
|
|
102
|
-
s3_open,
|
|
103
|
-
s3_path_join,
|
|
104
10
|
s3_pipe_open,
|
|
105
11
|
s3_prefetch_open,
|
|
106
|
-
|
|
107
|
-
s3_remove,
|
|
108
|
-
s3_rename,
|
|
109
|
-
s3_save_as,
|
|
110
|
-
s3_scan,
|
|
111
|
-
s3_scan_stat,
|
|
112
|
-
s3_scandir,
|
|
113
|
-
s3_stat,
|
|
114
|
-
s3_symlink,
|
|
115
|
-
s3_sync,
|
|
116
|
-
s3_unlink,
|
|
117
|
-
s3_upload,
|
|
118
|
-
s3_walk,
|
|
119
|
-
)
|
|
120
|
-
from megfile.s3_path import S3Path
|
|
121
|
-
from megfile.sftp import (
|
|
122
|
-
is_sftp,
|
|
123
|
-
sftp_absolute,
|
|
124
|
-
sftp_add_host_key,
|
|
125
|
-
sftp_chmod,
|
|
126
|
-
sftp_concat,
|
|
127
|
-
sftp_copy,
|
|
128
|
-
sftp_exists,
|
|
129
|
-
sftp_getmd5,
|
|
130
|
-
sftp_getmtime,
|
|
131
|
-
sftp_getsize,
|
|
132
|
-
sftp_glob,
|
|
133
|
-
sftp_glob_stat,
|
|
134
|
-
sftp_iglob,
|
|
135
|
-
sftp_isdir,
|
|
136
|
-
sftp_isfile,
|
|
137
|
-
sftp_islink,
|
|
138
|
-
sftp_listdir,
|
|
139
|
-
sftp_load_from,
|
|
140
|
-
sftp_lstat,
|
|
141
|
-
sftp_makedirs,
|
|
142
|
-
sftp_move,
|
|
143
|
-
sftp_open,
|
|
144
|
-
sftp_path_join,
|
|
145
|
-
sftp_readlink,
|
|
146
|
-
sftp_realpath,
|
|
147
|
-
sftp_remove,
|
|
148
|
-
sftp_rename,
|
|
149
|
-
sftp_resolve,
|
|
150
|
-
sftp_rmdir,
|
|
151
|
-
sftp_save_as,
|
|
152
|
-
sftp_scan,
|
|
153
|
-
sftp_scan_stat,
|
|
154
|
-
sftp_scandir,
|
|
155
|
-
sftp_stat,
|
|
156
|
-
sftp_symlink,
|
|
157
|
-
sftp_sync,
|
|
158
|
-
sftp_unlink,
|
|
159
|
-
sftp_walk,
|
|
12
|
+
s3_share_cache_open,
|
|
160
13
|
)
|
|
161
|
-
from megfile.sftp_path import SftpPath
|
|
14
|
+
from megfile.sftp_path import SftpPath, is_sftp, sftp_add_host_key
|
|
162
15
|
from megfile.smart import (
|
|
163
16
|
smart_access,
|
|
164
17
|
smart_cache,
|
|
@@ -202,8 +55,7 @@ from megfile.smart import (
|
|
|
202
55
|
smart_walk,
|
|
203
56
|
)
|
|
204
57
|
from megfile.smart_path import SmartPath
|
|
205
|
-
from megfile.
|
|
206
|
-
from megfile.stdio_path import StdioPath
|
|
58
|
+
from megfile.stdio_path import StdioPath, is_stdio
|
|
207
59
|
from megfile.version import VERSION as __version__ # noqa: F401
|
|
208
60
|
|
|
209
61
|
try:
|
|
@@ -212,9 +64,9 @@ except ImportError:
|
|
|
212
64
|
Sftp2Path = None
|
|
213
65
|
|
|
214
66
|
try:
|
|
215
|
-
from megfile.webdav_path import WebdavPath
|
|
67
|
+
from megfile.webdav_path import WebdavPath, is_webdav
|
|
216
68
|
except ImportError:
|
|
217
|
-
WebdavPath = None
|
|
69
|
+
WebdavPath = is_webdav = None
|
|
218
70
|
|
|
219
71
|
__all__ = [
|
|
220
72
|
"smart_access",
|
|
@@ -259,153 +111,21 @@ __all__ = [
|
|
|
259
111
|
"smart_lstat",
|
|
260
112
|
"smart_concat",
|
|
261
113
|
"is_s3",
|
|
262
|
-
"s3_access",
|
|
263
114
|
"s3_buffered_open",
|
|
264
115
|
"s3_cached_open",
|
|
265
|
-
"s3_copy",
|
|
266
|
-
"s3_download",
|
|
267
|
-
"s3_exists",
|
|
268
|
-
"s3_getmd5",
|
|
269
|
-
"s3_getmtime",
|
|
270
|
-
"s3_getsize",
|
|
271
|
-
"s3_glob_stat",
|
|
272
|
-
"s3_glob",
|
|
273
|
-
"s3_hasbucket",
|
|
274
|
-
"s3_iglob",
|
|
275
|
-
"s3_isdir",
|
|
276
|
-
"s3_isfile",
|
|
277
|
-
"s3_listdir",
|
|
278
|
-
"s3_load_content",
|
|
279
|
-
"s3_load_from",
|
|
280
|
-
"s3_makedirs",
|
|
281
116
|
"s3_memory_open",
|
|
282
|
-
"s3_open",
|
|
283
|
-
"s3_path_join",
|
|
284
117
|
"s3_pipe_open",
|
|
285
118
|
"s3_prefetch_open",
|
|
286
|
-
"
|
|
287
|
-
"s3_rename",
|
|
288
|
-
"s3_move",
|
|
289
|
-
"s3_sync",
|
|
290
|
-
"s3_save_as",
|
|
291
|
-
"s3_scan_stat",
|
|
292
|
-
"s3_scan",
|
|
293
|
-
"s3_scandir",
|
|
294
|
-
"s3_stat",
|
|
295
|
-
"s3_lstat",
|
|
296
|
-
"s3_unlink",
|
|
297
|
-
"s3_upload",
|
|
298
|
-
"s3_walk",
|
|
299
|
-
"s3_symlink",
|
|
300
|
-
"s3_readlink",
|
|
301
|
-
"s3_concat",
|
|
119
|
+
"s3_share_cache_open",
|
|
302
120
|
"is_fs",
|
|
303
|
-
"fs_abspath",
|
|
304
|
-
"fs_access",
|
|
305
|
-
"fs_exists",
|
|
306
|
-
"fs_getmtime",
|
|
307
|
-
"fs_getsize",
|
|
308
|
-
"fs_glob_stat",
|
|
309
|
-
"fs_glob",
|
|
310
|
-
"fs_iglob",
|
|
311
|
-
"fs_isabs",
|
|
312
|
-
"fs_isdir",
|
|
313
|
-
"fs_isfile",
|
|
314
|
-
"fs_islink",
|
|
315
|
-
"fs_ismount",
|
|
316
|
-
"fs_listdir",
|
|
317
|
-
"fs_load_from",
|
|
318
|
-
"fs_makedirs",
|
|
319
|
-
"fs_realpath",
|
|
320
|
-
"fs_relpath",
|
|
321
|
-
"fs_remove",
|
|
322
|
-
"fs_rename",
|
|
323
|
-
"fs_move",
|
|
324
|
-
"fs_sync",
|
|
325
|
-
"fs_save_as",
|
|
326
|
-
"fs_scan_stat",
|
|
327
|
-
"fs_scan",
|
|
328
|
-
"fs_scandir",
|
|
329
|
-
"fs_stat",
|
|
330
|
-
"fs_lstat",
|
|
331
|
-
"fs_unlink",
|
|
332
|
-
"fs_walk",
|
|
333
|
-
"fs_cwd",
|
|
334
|
-
"fs_home",
|
|
335
|
-
"fs_expanduser",
|
|
336
|
-
"fs_resolve",
|
|
337
|
-
"fs_getmd5",
|
|
338
|
-
"fs_symlink",
|
|
339
|
-
"fs_readlink",
|
|
340
121
|
"is_http",
|
|
341
|
-
"http_open",
|
|
342
|
-
"http_stat",
|
|
343
|
-
"http_getsize",
|
|
344
|
-
"http_getmtime",
|
|
345
|
-
"http_exists",
|
|
346
122
|
"is_stdio",
|
|
347
123
|
"stdio_open",
|
|
348
124
|
"is_sftp",
|
|
349
|
-
"sftp_readlink",
|
|
350
|
-
"sftp_absolute",
|
|
351
|
-
"sftp_glob",
|
|
352
|
-
"sftp_iglob",
|
|
353
|
-
"sftp_glob_stat",
|
|
354
|
-
"sftp_resolve",
|
|
355
|
-
"sftp_isdir",
|
|
356
|
-
"sftp_exists",
|
|
357
|
-
"sftp_scandir",
|
|
358
|
-
"sftp_getmtime",
|
|
359
|
-
"sftp_getsize",
|
|
360
|
-
"sftp_isfile",
|
|
361
|
-
"sftp_listdir",
|
|
362
|
-
"sftp_load_from",
|
|
363
|
-
"sftp_makedirs",
|
|
364
|
-
"sftp_realpath",
|
|
365
|
-
"sftp_rename",
|
|
366
|
-
"sftp_move",
|
|
367
|
-
"sftp_remove",
|
|
368
|
-
"sftp_scan",
|
|
369
|
-
"sftp_scan_stat",
|
|
370
|
-
"sftp_stat",
|
|
371
|
-
"sftp_lstat",
|
|
372
|
-
"sftp_unlink",
|
|
373
|
-
"sftp_walk",
|
|
374
|
-
"sftp_path_join",
|
|
375
|
-
"sftp_getmd5",
|
|
376
|
-
"sftp_symlink",
|
|
377
|
-
"sftp_islink",
|
|
378
|
-
"sftp_save_as",
|
|
379
|
-
"sftp_open",
|
|
380
|
-
"sftp_chmod",
|
|
381
|
-
"sftp_rmdir",
|
|
382
|
-
"sftp_copy",
|
|
383
|
-
"sftp_sync",
|
|
384
|
-
"sftp_concat",
|
|
385
125
|
"sftp_add_host_key",
|
|
386
126
|
"is_hdfs",
|
|
387
|
-
"
|
|
388
|
-
"
|
|
389
|
-
"hdfs_getmtime",
|
|
390
|
-
"hdfs_getsize",
|
|
391
|
-
"hdfs_isdir",
|
|
392
|
-
"hdfs_isfile",
|
|
393
|
-
"hdfs_listdir",
|
|
394
|
-
"hdfs_load_from",
|
|
395
|
-
"hdfs_move",
|
|
396
|
-
"hdfs_remove",
|
|
397
|
-
"hdfs_scan",
|
|
398
|
-
"hdfs_scan_stat",
|
|
399
|
-
"hdfs_scandir",
|
|
400
|
-
"hdfs_unlink",
|
|
401
|
-
"hdfs_walk",
|
|
402
|
-
"hdfs_getmd5",
|
|
403
|
-
"hdfs_save_as",
|
|
404
|
-
"hdfs_open",
|
|
405
|
-
"hdfs_glob",
|
|
406
|
-
"hdfs_glob_stat",
|
|
407
|
-
"hdfs_iglob",
|
|
408
|
-
"hdfs_makedirs",
|
|
127
|
+
"is_webdav",
|
|
128
|
+
"WebdavPath",
|
|
409
129
|
"S3Path",
|
|
410
130
|
"FSPath",
|
|
411
131
|
"HttpPath",
|
megfile/cli.py
CHANGED
|
@@ -19,7 +19,7 @@ from megfile.hdfs_path import DEFAULT_HDFS_TIMEOUT
|
|
|
19
19
|
from megfile.interfaces import FileEntry
|
|
20
20
|
from megfile.lib.glob import get_non_glob_dir, has_magic
|
|
21
21
|
from megfile.s3_path import get_s3_session
|
|
22
|
-
from megfile.
|
|
22
|
+
from megfile.sftp_path import sftp_add_host_key
|
|
23
23
|
from megfile.smart import (
|
|
24
24
|
_smart_sync_single_file,
|
|
25
25
|
smart_copy,
|
|
@@ -86,33 +86,33 @@ def safe_cli(): # pragma: no cover
|
|
|
86
86
|
sys.exit(1)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def get_echo_path(file_stat, base_path: str = "",
|
|
89
|
+
def get_echo_path(file_stat, base_path: str = "", full: bool = False):
|
|
90
90
|
if base_path == file_stat.path:
|
|
91
91
|
path = file_stat.name
|
|
92
|
-
elif
|
|
92
|
+
elif full:
|
|
93
93
|
path = file_stat.path
|
|
94
94
|
else:
|
|
95
95
|
path = smart_relpath(file_stat.path, start=base_path)
|
|
96
96
|
return path
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
def simple_echo(file_stat, base_path: str = "",
|
|
100
|
-
return get_echo_path(file_stat, base_path,
|
|
99
|
+
def simple_echo(file_stat, base_path: str = "", full: bool = False):
|
|
100
|
+
return get_echo_path(file_stat, base_path, full)
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def long_echo(file_stat, base_path: str = "",
|
|
103
|
+
def long_echo(file_stat, base_path: str = "", full: bool = False):
|
|
104
104
|
return "%12d %s %s" % (
|
|
105
105
|
file_stat.stat.size,
|
|
106
106
|
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
|
|
107
|
-
get_echo_path(file_stat, base_path,
|
|
107
|
+
get_echo_path(file_stat, base_path, full),
|
|
108
108
|
)
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
def human_echo(file_stat, base_path: str = "",
|
|
111
|
+
def human_echo(file_stat, base_path: str = "", full: bool = False):
|
|
112
112
|
return "%10s %s %s" % (
|
|
113
113
|
get_human_size(file_stat.stat.size),
|
|
114
114
|
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
|
|
115
|
-
get_echo_path(file_stat, base_path,
|
|
115
|
+
get_echo_path(file_stat, base_path, full),
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
|
|
@@ -143,13 +143,12 @@ def _sftp_prompt_host_key(path):
|
|
|
143
143
|
)
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
def _ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
146
|
+
def _ls(path: str, long: bool, full: bool, recursive: bool, human_readable: bool):
|
|
147
147
|
base_path = path
|
|
148
|
-
full_path = False
|
|
149
148
|
if has_magic(path):
|
|
150
149
|
scan_func = smart_glob_stat
|
|
151
150
|
base_path = get_non_glob_dir(path)
|
|
152
|
-
|
|
151
|
+
full = True
|
|
153
152
|
elif recursive:
|
|
154
153
|
scan_func = smart_scan_stat
|
|
155
154
|
else:
|
|
@@ -170,8 +169,8 @@ def _ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
|
170
169
|
for file_stat in scan_func(path):
|
|
171
170
|
total_size += file_stat.stat.size
|
|
172
171
|
total_count += 1
|
|
173
|
-
output = echo_func(file_stat, base_path,
|
|
174
|
-
if file_stat.is_symlink():
|
|
172
|
+
output = echo_func(file_stat, base_path, full=full)
|
|
173
|
+
if long and file_stat.is_symlink():
|
|
175
174
|
output += " -> %s" % smart_readlink(file_stat.path)
|
|
176
175
|
click.echo(output)
|
|
177
176
|
if long:
|
|
@@ -215,6 +214,12 @@ ZshComplete.source_template = ZshComplete.source_template.replace(
|
|
|
215
214
|
is_flag=True,
|
|
216
215
|
help="List all the objects in the path with size, modification time and path.",
|
|
217
216
|
)
|
|
217
|
+
@click.option(
|
|
218
|
+
"-f",
|
|
219
|
+
"--full",
|
|
220
|
+
is_flag=True,
|
|
221
|
+
help="Displays the full path of each file.",
|
|
222
|
+
)
|
|
218
223
|
@click.option(
|
|
219
224
|
"-r",
|
|
220
225
|
"--recursive",
|
|
@@ -228,12 +233,24 @@ ZshComplete.source_template = ZshComplete.source_template.replace(
|
|
|
228
233
|
is_flag=True,
|
|
229
234
|
help="Displays file sizes in human readable format.",
|
|
230
235
|
)
|
|
231
|
-
def ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
232
|
-
_ls(
|
|
236
|
+
def ls(path: str, long: bool, full: bool, recursive: bool, human_readable: bool):
|
|
237
|
+
_ls(
|
|
238
|
+
path,
|
|
239
|
+
long=long,
|
|
240
|
+
full=full,
|
|
241
|
+
recursive=recursive,
|
|
242
|
+
human_readable=human_readable,
|
|
243
|
+
)
|
|
233
244
|
|
|
234
245
|
|
|
235
246
|
@cli.command(short_help="List all the objects in the path.")
|
|
236
247
|
@click.argument("path", type=PathType())
|
|
248
|
+
@click.option(
|
|
249
|
+
"-f",
|
|
250
|
+
"--full",
|
|
251
|
+
is_flag=True,
|
|
252
|
+
help="Displays the full path of each file.",
|
|
253
|
+
)
|
|
237
254
|
@click.option(
|
|
238
255
|
"-r",
|
|
239
256
|
"--recursive",
|
|
@@ -241,8 +258,8 @@ def ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
|
241
258
|
help="Command is performed on all files or objects under "
|
|
242
259
|
"the specified directory or prefix.",
|
|
243
260
|
)
|
|
244
|
-
def ll(path: str, recursive: bool):
|
|
245
|
-
_ls(path, long=True, recursive=recursive, human_readable=True)
|
|
261
|
+
def ll(path: str, recursive: bool, full: bool):
|
|
262
|
+
_ls(path, long=True, full=full, recursive=recursive, human_readable=True)
|
|
246
263
|
|
|
247
264
|
|
|
248
265
|
@cli.command(short_help="Copy files from source to dest, skipping already copied.")
|
|
@@ -342,8 +359,8 @@ def mv(
|
|
|
342
359
|
_sftp_prompt_host_key(dst_path)
|
|
343
360
|
|
|
344
361
|
if progress_bar:
|
|
345
|
-
src_protocol
|
|
346
|
-
dst_protocol
|
|
362
|
+
src_protocol = SmartPath._extract_protocol(src_path)
|
|
363
|
+
dst_protocol = SmartPath._extract_protocol(dst_path)
|
|
347
364
|
|
|
348
365
|
if recursive:
|
|
349
366
|
if src_protocol == dst_protocol:
|
megfile/config.py
CHANGED
|
@@ -125,10 +125,19 @@ HDFS_MAX_RETRY_TIMES = int(
|
|
|
125
125
|
SFTP_MAX_RETRY_TIMES = int(
|
|
126
126
|
os.getenv("MEGFILE_SFTP_MAX_RETRY_TIMES") or DEFAULT_MAX_RETRY_TIMES
|
|
127
127
|
)
|
|
128
|
+
WEBDAV_MAX_RETRY_TIMES = int(
|
|
129
|
+
os.getenv("MEGFILE_WEBDAV_MAX_RETRY_TIMES") or DEFAULT_MAX_RETRY_TIMES
|
|
130
|
+
)
|
|
128
131
|
|
|
129
132
|
SFTP_HOST_KEY_POLICY = os.getenv("MEGFILE_SFTP_HOST_KEY_POLICY")
|
|
130
133
|
|
|
131
|
-
HTTP_AUTH_HEADERS = (
|
|
134
|
+
HTTP_AUTH_HEADERS = (
|
|
135
|
+
"Authorization",
|
|
136
|
+
"Www-Authenticate",
|
|
137
|
+
"Cookie",
|
|
138
|
+
"Cookie2",
|
|
139
|
+
"X-Amz-Security-Token",
|
|
140
|
+
)
|
|
132
141
|
|
|
133
142
|
if os.getenv("MEGFILE_LOG_LEVEL"):
|
|
134
143
|
set_log_level()
|
megfile/errors.py
CHANGED
|
@@ -50,8 +50,7 @@ _logger = getLogger(__name__)
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def s3_endpoint_url(path: Optional[PathLike] = None):
|
|
53
|
-
from megfile.
|
|
54
|
-
from megfile.s3_path import S3Path
|
|
53
|
+
from megfile.s3_path import S3Path, get_endpoint_url, get_s3_client
|
|
55
54
|
|
|
56
55
|
profile_name = None
|
|
57
56
|
if path:
|
|
@@ -137,6 +136,7 @@ s3_retry_error_codes = (
|
|
|
137
136
|
"UploadTrafficRateLimitExceeded",
|
|
138
137
|
"MetaOperationQpsLimitExceeded",
|
|
139
138
|
"TotalQpsLimitExceeded",
|
|
139
|
+
"PartitionQpsLimitted",
|
|
140
140
|
"ActiveRequestLimitExceeded",
|
|
141
141
|
"CpuLimitExceeded",
|
|
142
142
|
"QpsLimitExceeded",
|
megfile/fs_path.py
CHANGED
|
@@ -33,7 +33,7 @@ from megfile.utils import calculate_md5, copyfd
|
|
|
33
33
|
__all__ = [
|
|
34
34
|
"FSPath",
|
|
35
35
|
"is_fs",
|
|
36
|
-
"
|
|
36
|
+
"fs_copy",
|
|
37
37
|
]
|
|
38
38
|
|
|
39
39
|
|
|
@@ -61,8 +61,37 @@ def is_fs(path: Union["PathLike", int]) -> bool:
|
|
|
61
61
|
return scheme == "" or scheme == "file"
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
def
|
|
65
|
-
|
|
64
|
+
def fs_copy(
|
|
65
|
+
src_path: PathLike,
|
|
66
|
+
dst_path: PathLike,
|
|
67
|
+
callback: Optional[Callable[[int], None]] = None,
|
|
68
|
+
followlinks: bool = False,
|
|
69
|
+
overwrite: bool = True,
|
|
70
|
+
):
|
|
71
|
+
"""File copy on file system
|
|
72
|
+
Copy content (excluding meta date) of file on `src_path` to `dst_path`.
|
|
73
|
+
`dst_path` must be a complete file name
|
|
74
|
+
|
|
75
|
+
.. note ::
|
|
76
|
+
|
|
77
|
+
The differences between this function and shutil.copyfile are:
|
|
78
|
+
|
|
79
|
+
1. If parent directory of dst_path doesn't exist, create it
|
|
80
|
+
|
|
81
|
+
2. Allow callback function, None by default.
|
|
82
|
+
callback: Optional[Callable[[int], None]], the int data is means
|
|
83
|
+
the size (in bytes) of the written data that is passed periodically
|
|
84
|
+
|
|
85
|
+
3. This function is thread-unsafe
|
|
86
|
+
|
|
87
|
+
:param src_path: Given path
|
|
88
|
+
:param dst_path: Target file path
|
|
89
|
+
:param callback: Called periodically during copy, and the input parameter is
|
|
90
|
+
the data size (in bytes) of copy since the last call
|
|
91
|
+
:param followlinks: False if regard symlink as file, else True
|
|
92
|
+
:param overwrite: whether or not overwrite file when exists, default is True
|
|
93
|
+
"""
|
|
94
|
+
return FSPath(src_path).copy(dst_path, callback, followlinks, overwrite)
|
|
66
95
|
|
|
67
96
|
|
|
68
97
|
def _fs_rename_file(
|
megfile/interfaces.py
CHANGED
|
@@ -68,6 +68,17 @@ class Closable(ABC):
|
|
|
68
68
|
def _abort(self) -> None:
|
|
69
69
|
pass
|
|
70
70
|
|
|
71
|
+
def abort(self) -> bool:
|
|
72
|
+
"""Abort the file-like object without saving.
|
|
73
|
+
|
|
74
|
+
This method has no effect if the file is already closed.
|
|
75
|
+
"""
|
|
76
|
+
if not getattr(self, "__closed__", False):
|
|
77
|
+
self._abort()
|
|
78
|
+
setattr(self, "__closed__", True)
|
|
79
|
+
return True
|
|
80
|
+
return False
|
|
81
|
+
|
|
71
82
|
def close(self) -> None:
|
|
72
83
|
"""Flush and close the file-like object.
|
|
73
84
|
|
|
@@ -82,22 +93,22 @@ class Closable(ABC):
|
|
|
82
93
|
|
|
83
94
|
def __exit__(self, type, value, traceback) -> None:
|
|
84
95
|
if self.atomic and value is not None:
|
|
85
|
-
|
|
96
|
+
if self.abort():
|
|
97
|
+
from megfile.errors import full_error_message
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self._abort()
|
|
99
|
+
_logger.warning(
|
|
100
|
+
f"skip closing atomic file-like object: {self}, "
|
|
101
|
+
f"since error encountered: {full_error_message(value)}"
|
|
102
|
+
)
|
|
92
103
|
return
|
|
93
104
|
self.close()
|
|
94
105
|
|
|
95
106
|
def __del__(self):
|
|
96
107
|
if self.atomic:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
108
|
+
if self.abort():
|
|
109
|
+
_logger.warning(
|
|
110
|
+
f"skip closing atomic file-like object before deletion: {self}"
|
|
111
|
+
)
|
|
101
112
|
return
|
|
102
113
|
self.close()
|
|
103
114
|
|