megfile 4.2.5__py3-none-any.whl → 5.0.1__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 +14 -291
- megfile/cli.py +83 -40
- megfile/config.py +35 -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 +198 -96
- megfile/version.py +1 -1
- megfile/webdav_path.py +161 -166
- {megfile-4.2.5.dist-info → megfile-5.0.1.dist-info}/METADATA +27 -39
- megfile-5.0.1.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.1.dist-info}/WHEEL +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.1.dist-info}/entry_points.txt +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.1.dist-info}/licenses/LICENSE +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.1.dist-info}/licenses/LICENSE.pyre +0 -0
- {megfile-4.2.5.dist-info → megfile-5.0.1.dist-info}/top_level.txt +0 -0
megfile/__init__.py
CHANGED
|
@@ -1,164 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
+
import megfile.config # noqa: F401 # make sure env config is loaded
|
|
2
|
+
from megfile.fs_path import FSPath, is_fs
|
|
3
|
+
from megfile.hdfs_path import HdfsPath, is_hdfs
|
|
4
|
+
from megfile.http_path import HttpPath, HttpsPath, is_http
|
|
5
|
+
from megfile.s3_path import (
|
|
6
|
+
S3Path,
|
|
78
7
|
is_s3,
|
|
79
|
-
s3_access,
|
|
80
8
|
s3_buffered_open,
|
|
81
9
|
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
10
|
s3_memory_open,
|
|
101
|
-
s3_move,
|
|
102
11
|
s3_open,
|
|
103
|
-
s3_path_join,
|
|
104
12
|
s3_pipe_open,
|
|
105
13
|
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,
|
|
14
|
+
s3_share_cache_open,
|
|
160
15
|
)
|
|
161
|
-
from megfile.sftp_path import SftpPath
|
|
16
|
+
from megfile.sftp_path import SftpPath, is_sftp, sftp_add_host_key
|
|
162
17
|
from megfile.smart import (
|
|
163
18
|
smart_access,
|
|
164
19
|
smart_cache,
|
|
@@ -202,8 +57,7 @@ from megfile.smart import (
|
|
|
202
57
|
smart_walk,
|
|
203
58
|
)
|
|
204
59
|
from megfile.smart_path import SmartPath
|
|
205
|
-
from megfile.
|
|
206
|
-
from megfile.stdio_path import StdioPath
|
|
60
|
+
from megfile.stdio_path import StdioPath, is_stdio
|
|
207
61
|
from megfile.version import VERSION as __version__ # noqa: F401
|
|
208
62
|
|
|
209
63
|
try:
|
|
@@ -212,9 +66,9 @@ except ImportError:
|
|
|
212
66
|
Sftp2Path = None
|
|
213
67
|
|
|
214
68
|
try:
|
|
215
|
-
from megfile.webdav_path import WebdavPath
|
|
69
|
+
from megfile.webdav_path import WebdavPath, is_webdav
|
|
216
70
|
except ImportError:
|
|
217
|
-
WebdavPath = None
|
|
71
|
+
WebdavPath = is_webdav = None
|
|
218
72
|
|
|
219
73
|
__all__ = [
|
|
220
74
|
"smart_access",
|
|
@@ -259,153 +113,22 @@ __all__ = [
|
|
|
259
113
|
"smart_lstat",
|
|
260
114
|
"smart_concat",
|
|
261
115
|
"is_s3",
|
|
262
|
-
"s3_access",
|
|
263
116
|
"s3_buffered_open",
|
|
264
117
|
"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
118
|
"s3_memory_open",
|
|
282
119
|
"s3_open",
|
|
283
|
-
"s3_path_join",
|
|
284
120
|
"s3_pipe_open",
|
|
285
121
|
"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",
|
|
122
|
+
"s3_share_cache_open",
|
|
302
123
|
"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
124
|
"is_http",
|
|
341
|
-
"http_open",
|
|
342
|
-
"http_stat",
|
|
343
|
-
"http_getsize",
|
|
344
|
-
"http_getmtime",
|
|
345
|
-
"http_exists",
|
|
346
125
|
"is_stdio",
|
|
347
126
|
"stdio_open",
|
|
348
127
|
"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
128
|
"sftp_add_host_key",
|
|
386
129
|
"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",
|
|
130
|
+
"is_webdav",
|
|
131
|
+
"WebdavPath",
|
|
409
132
|
"S3Path",
|
|
410
133
|
"FSPath",
|
|
411
134
|
"HttpPath",
|
megfile/cli.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import configparser
|
|
2
1
|
import os
|
|
3
2
|
import shutil
|
|
4
3
|
import signal
|
|
@@ -14,12 +13,18 @@ from click import ParamType
|
|
|
14
13
|
from click.shell_completion import CompletionItem, ZshComplete
|
|
15
14
|
from tqdm import tqdm
|
|
16
15
|
|
|
17
|
-
from megfile.config import
|
|
16
|
+
from megfile.config import (
|
|
17
|
+
CONFIG_PATH,
|
|
18
|
+
READER_BLOCK_SIZE,
|
|
19
|
+
SFTP_HOST_KEY_POLICY,
|
|
20
|
+
CaseSensitiveConfigParser,
|
|
21
|
+
set_log_level,
|
|
22
|
+
)
|
|
18
23
|
from megfile.hdfs_path import DEFAULT_HDFS_TIMEOUT
|
|
19
24
|
from megfile.interfaces import FileEntry
|
|
20
25
|
from megfile.lib.glob import get_non_glob_dir, has_magic
|
|
21
26
|
from megfile.s3_path import get_s3_session
|
|
22
|
-
from megfile.
|
|
27
|
+
from megfile.sftp_path import sftp_add_host_key
|
|
23
28
|
from megfile.smart import (
|
|
24
29
|
_smart_sync_single_file,
|
|
25
30
|
smart_copy,
|
|
@@ -86,33 +91,33 @@ def safe_cli(): # pragma: no cover
|
|
|
86
91
|
sys.exit(1)
|
|
87
92
|
|
|
88
93
|
|
|
89
|
-
def get_echo_path(file_stat, base_path: str = "",
|
|
94
|
+
def get_echo_path(file_stat, base_path: str = "", full: bool = False):
|
|
90
95
|
if base_path == file_stat.path:
|
|
91
96
|
path = file_stat.name
|
|
92
|
-
elif
|
|
97
|
+
elif full:
|
|
93
98
|
path = file_stat.path
|
|
94
99
|
else:
|
|
95
100
|
path = smart_relpath(file_stat.path, start=base_path)
|
|
96
101
|
return path
|
|
97
102
|
|
|
98
103
|
|
|
99
|
-
def simple_echo(file_stat, base_path: str = "",
|
|
100
|
-
return get_echo_path(file_stat, base_path,
|
|
104
|
+
def simple_echo(file_stat, base_path: str = "", full: bool = False):
|
|
105
|
+
return get_echo_path(file_stat, base_path, full)
|
|
101
106
|
|
|
102
107
|
|
|
103
|
-
def long_echo(file_stat, base_path: str = "",
|
|
108
|
+
def long_echo(file_stat, base_path: str = "", full: bool = False):
|
|
104
109
|
return "%12d %s %s" % (
|
|
105
110
|
file_stat.stat.size,
|
|
106
111
|
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
|
|
107
|
-
get_echo_path(file_stat, base_path,
|
|
112
|
+
get_echo_path(file_stat, base_path, full),
|
|
108
113
|
)
|
|
109
114
|
|
|
110
115
|
|
|
111
|
-
def human_echo(file_stat, base_path: str = "",
|
|
116
|
+
def human_echo(file_stat, base_path: str = "", full: bool = False):
|
|
112
117
|
return "%10s %s %s" % (
|
|
113
118
|
get_human_size(file_stat.stat.size),
|
|
114
119
|
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
|
|
115
|
-
get_echo_path(file_stat, base_path,
|
|
120
|
+
get_echo_path(file_stat, base_path, full),
|
|
116
121
|
)
|
|
117
122
|
|
|
118
123
|
|
|
@@ -143,13 +148,12 @@ def _sftp_prompt_host_key(path):
|
|
|
143
148
|
)
|
|
144
149
|
|
|
145
150
|
|
|
146
|
-
def _ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
151
|
+
def _ls(path: str, long: bool, full: bool, recursive: bool, human_readable: bool):
|
|
147
152
|
base_path = path
|
|
148
|
-
full_path = False
|
|
149
153
|
if has_magic(path):
|
|
150
154
|
scan_func = smart_glob_stat
|
|
151
155
|
base_path = get_non_glob_dir(path)
|
|
152
|
-
|
|
156
|
+
full = True
|
|
153
157
|
elif recursive:
|
|
154
158
|
scan_func = smart_scan_stat
|
|
155
159
|
else:
|
|
@@ -170,8 +174,8 @@ def _ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
|
170
174
|
for file_stat in scan_func(path):
|
|
171
175
|
total_size += file_stat.stat.size
|
|
172
176
|
total_count += 1
|
|
173
|
-
output = echo_func(file_stat, base_path,
|
|
174
|
-
if file_stat.is_symlink():
|
|
177
|
+
output = echo_func(file_stat, base_path, full=full)
|
|
178
|
+
if long and file_stat.is_symlink():
|
|
175
179
|
output += " -> %s" % smart_readlink(file_stat.path)
|
|
176
180
|
click.echo(output)
|
|
177
181
|
if long:
|
|
@@ -215,6 +219,12 @@ ZshComplete.source_template = ZshComplete.source_template.replace(
|
|
|
215
219
|
is_flag=True,
|
|
216
220
|
help="List all the objects in the path with size, modification time and path.",
|
|
217
221
|
)
|
|
222
|
+
@click.option(
|
|
223
|
+
"-f",
|
|
224
|
+
"--full",
|
|
225
|
+
is_flag=True,
|
|
226
|
+
help="Displays the full path of each file.",
|
|
227
|
+
)
|
|
218
228
|
@click.option(
|
|
219
229
|
"-r",
|
|
220
230
|
"--recursive",
|
|
@@ -228,12 +238,24 @@ ZshComplete.source_template = ZshComplete.source_template.replace(
|
|
|
228
238
|
is_flag=True,
|
|
229
239
|
help="Displays file sizes in human readable format.",
|
|
230
240
|
)
|
|
231
|
-
def ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
232
|
-
_ls(
|
|
241
|
+
def ls(path: str, long: bool, full: bool, recursive: bool, human_readable: bool):
|
|
242
|
+
_ls(
|
|
243
|
+
path,
|
|
244
|
+
long=long,
|
|
245
|
+
full=full,
|
|
246
|
+
recursive=recursive,
|
|
247
|
+
human_readable=human_readable,
|
|
248
|
+
)
|
|
233
249
|
|
|
234
250
|
|
|
235
251
|
@cli.command(short_help="List all the objects in the path.")
|
|
236
252
|
@click.argument("path", type=PathType())
|
|
253
|
+
@click.option(
|
|
254
|
+
"-f",
|
|
255
|
+
"--full",
|
|
256
|
+
is_flag=True,
|
|
257
|
+
help="Displays the full path of each file.",
|
|
258
|
+
)
|
|
237
259
|
@click.option(
|
|
238
260
|
"-r",
|
|
239
261
|
"--recursive",
|
|
@@ -241,8 +263,8 @@ def ls(path: str, long: bool, recursive: bool, human_readable: bool):
|
|
|
241
263
|
help="Command is performed on all files or objects under "
|
|
242
264
|
"the specified directory or prefix.",
|
|
243
265
|
)
|
|
244
|
-
def ll(path: str, recursive: bool):
|
|
245
|
-
_ls(path, long=True, recursive=recursive, human_readable=True)
|
|
266
|
+
def ll(path: str, recursive: bool, full: bool):
|
|
267
|
+
_ls(path, long=True, full=full, recursive=recursive, human_readable=True)
|
|
246
268
|
|
|
247
269
|
|
|
248
270
|
@cli.command(short_help="Copy files from source to dest, skipping already copied.")
|
|
@@ -342,8 +364,8 @@ def mv(
|
|
|
342
364
|
_sftp_prompt_host_key(dst_path)
|
|
343
365
|
|
|
344
366
|
if progress_bar:
|
|
345
|
-
src_protocol
|
|
346
|
-
dst_protocol
|
|
367
|
+
src_protocol = SmartPath._extract_protocol(src_path)
|
|
368
|
+
dst_protocol = SmartPath._extract_protocol(dst_path)
|
|
347
369
|
|
|
348
370
|
if recursive:
|
|
349
371
|
if src_protocol == dst_protocol:
|
|
@@ -824,7 +846,7 @@ def hdfs(path, url, profile_name, user, root, token, timeout, no_cover):
|
|
|
824
846
|
"timeout": timeout,
|
|
825
847
|
}
|
|
826
848
|
profile_name = f"{profile_name}.alias"
|
|
827
|
-
config =
|
|
849
|
+
config = CaseSensitiveConfigParser()
|
|
828
850
|
if os.path.exists(path):
|
|
829
851
|
config.read(path)
|
|
830
852
|
if "global" not in config.sections():
|
|
@@ -848,37 +870,58 @@ def hdfs(path, url, profile_name, user, root, token, timeout, no_cover):
|
|
|
848
870
|
@click.option(
|
|
849
871
|
"-p",
|
|
850
872
|
"--path",
|
|
851
|
-
default=
|
|
852
|
-
help="
|
|
873
|
+
default=CONFIG_PATH,
|
|
874
|
+
help=f"megfile config file, default is {CONFIG_PATH}",
|
|
853
875
|
)
|
|
854
876
|
@click.argument("name")
|
|
855
877
|
@click.argument("protocol_or_path")
|
|
856
878
|
@click.option("--no-cover", is_flag=True, help="Not cover the same-name config")
|
|
857
879
|
def alias(path, name, protocol_or_path, no_cover):
|
|
858
880
|
path = os.path.expanduser(path)
|
|
859
|
-
config =
|
|
881
|
+
config = CaseSensitiveConfigParser()
|
|
860
882
|
if os.path.exists(path):
|
|
861
883
|
config.read(path)
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
config[name] = {
|
|
868
|
-
"protocol": protocol,
|
|
869
|
-
"prefix": prefix,
|
|
870
|
-
}
|
|
871
|
-
else:
|
|
872
|
-
config[name] = {
|
|
873
|
-
"protocol": protocol_or_path,
|
|
874
|
-
}
|
|
875
|
-
|
|
884
|
+
config.setdefault("alias", {})
|
|
885
|
+
if config.has_option("alias", name) and no_cover:
|
|
886
|
+
value = config.get("alias", name)
|
|
887
|
+
raise NameError(f"alias-name has been used: {name} = {value}")
|
|
888
|
+
config.set("alias", name, protocol_or_path)
|
|
876
889
|
_safe_makedirs(os.path.dirname(path)) # make sure dirpath exist
|
|
877
890
|
with open(path, "w") as fp:
|
|
878
891
|
config.write(fp)
|
|
879
892
|
click.echo(f"Your alias config has been saved into {path}")
|
|
880
893
|
|
|
881
894
|
|
|
895
|
+
@config.command(short_help="Update the config file for envs")
|
|
896
|
+
@click.option(
|
|
897
|
+
"-p",
|
|
898
|
+
"--path",
|
|
899
|
+
default=CONFIG_PATH,
|
|
900
|
+
help=f"megfile config file, default is {CONFIG_PATH}",
|
|
901
|
+
)
|
|
902
|
+
@click.argument("expr")
|
|
903
|
+
@click.option("--no-cover", is_flag=True, help="Not cover the same-name config")
|
|
904
|
+
def env(path, expr, no_cover):
|
|
905
|
+
if "=" not in expr:
|
|
906
|
+
raise ValueError("Invalid env format: {}".format(expr))
|
|
907
|
+
name, value = expr.split("=", 1)
|
|
908
|
+
|
|
909
|
+
path = os.path.expanduser(path)
|
|
910
|
+
|
|
911
|
+
config = CaseSensitiveConfigParser()
|
|
912
|
+
if os.path.exists(path):
|
|
913
|
+
config.read(path)
|
|
914
|
+
config.setdefault("env", {})
|
|
915
|
+
if config.has_option("env", name) and no_cover:
|
|
916
|
+
value = config.get("env", name)
|
|
917
|
+
raise NameError(f"env has been set: {name} = {value}")
|
|
918
|
+
config.set("env", name, value)
|
|
919
|
+
_safe_makedirs(os.path.dirname(path)) # make sure dirpath exist
|
|
920
|
+
with open(path, "w") as fp:
|
|
921
|
+
config.write(fp)
|
|
922
|
+
click.echo(f"Your env config has been saved into {path}")
|
|
923
|
+
|
|
924
|
+
|
|
882
925
|
@cli.group(short_help="Return the completion file")
|
|
883
926
|
def completion():
|
|
884
927
|
pass
|
megfile/config.py
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import configparser
|
|
1
2
|
import logging
|
|
2
3
|
import os
|
|
3
4
|
import typing as T
|
|
4
5
|
|
|
5
6
|
|
|
7
|
+
class CaseSensitiveConfigParser(configparser.ConfigParser):
|
|
8
|
+
def optionxform(self, optionstr: str) -> str:
|
|
9
|
+
return optionstr
|
|
10
|
+
|
|
11
|
+
|
|
6
12
|
def parse_quantity(quantity: T.Union[str, int]) -> int:
|
|
7
13
|
"""
|
|
8
14
|
Parse kubernetes canonical form quantity like 200Mi to a int number.
|
|
@@ -75,6 +81,25 @@ def set_log_level(level: T.Optional[T.Union[int, str]] = None):
|
|
|
75
81
|
logging.getLogger("megfile").setLevel(level)
|
|
76
82
|
|
|
77
83
|
|
|
84
|
+
CONFIG_PATH = "~/.config/megfile/megfile.conf"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def load_megfile_config(section) -> T.Dict[str, str]:
|
|
88
|
+
path = os.path.expanduser(CONFIG_PATH)
|
|
89
|
+
if not os.path.isfile(path):
|
|
90
|
+
return {}
|
|
91
|
+
config = CaseSensitiveConfigParser()
|
|
92
|
+
if os.path.exists(path):
|
|
93
|
+
config.read(path)
|
|
94
|
+
if not config.has_section(section):
|
|
95
|
+
return {}
|
|
96
|
+
return dict(config.items(section))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
for key, value in load_megfile_config("env").items():
|
|
100
|
+
os.environ.setdefault(key.upper(), value)
|
|
101
|
+
|
|
102
|
+
|
|
78
103
|
READER_BLOCK_SIZE = parse_quantity(os.getenv("MEGFILE_READER_BLOCK_SIZE") or 8 * 2**20)
|
|
79
104
|
if READER_BLOCK_SIZE <= 0:
|
|
80
105
|
raise ValueError(
|
|
@@ -125,10 +150,19 @@ HDFS_MAX_RETRY_TIMES = int(
|
|
|
125
150
|
SFTP_MAX_RETRY_TIMES = int(
|
|
126
151
|
os.getenv("MEGFILE_SFTP_MAX_RETRY_TIMES") or DEFAULT_MAX_RETRY_TIMES
|
|
127
152
|
)
|
|
153
|
+
WEBDAV_MAX_RETRY_TIMES = int(
|
|
154
|
+
os.getenv("MEGFILE_WEBDAV_MAX_RETRY_TIMES") or DEFAULT_MAX_RETRY_TIMES
|
|
155
|
+
)
|
|
128
156
|
|
|
129
157
|
SFTP_HOST_KEY_POLICY = os.getenv("MEGFILE_SFTP_HOST_KEY_POLICY")
|
|
130
158
|
|
|
131
|
-
HTTP_AUTH_HEADERS = (
|
|
159
|
+
HTTP_AUTH_HEADERS = (
|
|
160
|
+
"Authorization",
|
|
161
|
+
"Www-Authenticate",
|
|
162
|
+
"Cookie",
|
|
163
|
+
"Cookie2",
|
|
164
|
+
"X-Amz-Security-Token",
|
|
165
|
+
)
|
|
132
166
|
|
|
133
167
|
if os.getenv("MEGFILE_LOG_LEVEL"):
|
|
134
168
|
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",
|