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 CHANGED
@@ -1,164 +1,17 @@
1
- from megfile.fs import (
2
- fs_abspath,
3
- fs_access,
4
- fs_cwd,
5
- fs_exists,
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
- s3_readlink,
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.stdio import is_stdio, stdio_open
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
- "s3_remove",
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
- "hdfs_exists",
388
- "hdfs_stat",
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.sftp import sftp_add_host_key
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 = "", full_path: bool = False):
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 full_path:
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 = "", full_path: bool = False):
100
- return get_echo_path(file_stat, base_path, full_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 = "", full_path: bool = False):
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, full_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 = "", full_path: bool = False):
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, full_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
- full_path = True
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, full_path=full_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(path, long=long, recursive=recursive, human_readable=human_readable)
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, _ = SmartPath._extract_protocol(src_path)
346
- dst_protocol, _ = SmartPath._extract_protocol(dst_path)
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 = ("Authorization", "Www-Authenticate", "Cookie", "Cookie2")
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.s3 import get_endpoint_url, get_s3_client
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
- "fs_path_join",
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 fs_path_join(path: PathLike, *other_paths: PathLike) -> str:
65
- return path_join(fspath(path), *map(fspath, other_paths))
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
- from megfile.errors import full_error_message
96
+ if self.abort():
97
+ from megfile.errors import full_error_message
86
98
 
87
- _logger.warning(
88
- f"skip closing atomic file-like object: {self}, "
89
- f"since error encountered: {full_error_message(value)}"
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
- _logger.warning(
98
- f"skip closing atomic file-like object before deletion: {self}"
99
- )
100
- self._abort()
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