megfile 3.1.1__py3-none-any.whl → 3.1.2__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.
- docs/conf.py +2 -4
- megfile/__init__.py +394 -203
- megfile/cli.py +258 -238
- megfile/config.py +25 -21
- megfile/errors.py +124 -114
- megfile/fs.py +174 -140
- megfile/fs_path.py +462 -354
- megfile/hdfs.py +133 -101
- megfile/hdfs_path.py +290 -236
- megfile/http.py +15 -14
- megfile/http_path.py +111 -107
- megfile/interfaces.py +70 -65
- megfile/lib/base_prefetch_reader.py +84 -65
- megfile/lib/combine_reader.py +12 -12
- megfile/lib/compare.py +17 -13
- megfile/lib/compat.py +1 -5
- megfile/lib/fnmatch.py +29 -30
- megfile/lib/glob.py +46 -54
- megfile/lib/hdfs_prefetch_reader.py +40 -25
- megfile/lib/hdfs_tools.py +1 -3
- megfile/lib/http_prefetch_reader.py +69 -46
- megfile/lib/joinpath.py +5 -5
- megfile/lib/lazy_handler.py +7 -3
- megfile/lib/s3_buffered_writer.py +58 -51
- megfile/lib/s3_cached_handler.py +13 -14
- megfile/lib/s3_limited_seekable_writer.py +37 -28
- megfile/lib/s3_memory_handler.py +34 -30
- megfile/lib/s3_pipe_handler.py +24 -25
- megfile/lib/s3_prefetch_reader.py +71 -52
- megfile/lib/s3_share_cache_reader.py +37 -24
- megfile/lib/shadow_handler.py +7 -3
- megfile/lib/stdio_handler.py +9 -8
- megfile/lib/url.py +3 -3
- megfile/pathlike.py +259 -228
- megfile/s3.py +220 -153
- megfile/s3_path.py +977 -802
- megfile/sftp.py +190 -156
- megfile/sftp_path.py +540 -450
- megfile/smart.py +397 -330
- megfile/smart_path.py +100 -105
- megfile/stdio.py +10 -9
- megfile/stdio_path.py +32 -35
- megfile/utils/__init__.py +73 -54
- megfile/utils/mutex.py +11 -14
- megfile/version.py +1 -1
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/METADATA +5 -8
- megfile-3.1.2.dist-info/RECORD +55 -0
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/WHEEL +1 -1
- scripts/convert_results_to_sarif.py +45 -78
- scripts/generate_file.py +140 -64
- megfile-3.1.1.dist-info/RECORD +0 -55
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/LICENSE +0 -0
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/LICENSE.pyre +0 -0
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/entry_points.txt +0 -0
- {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/top_level.txt +0 -0
megfile/s3.py
CHANGED
|
@@ -1,303 +1,365 @@
|
|
|
1
1
|
from typing import BinaryIO, Callable, Iterator, List, Optional, Tuple
|
|
2
2
|
|
|
3
3
|
from megfile.interfaces import Access, FileEntry, PathLike, StatResult
|
|
4
|
-
from megfile.s3_path import
|
|
4
|
+
from megfile.s3_path import (
|
|
5
|
+
S3BufferedWriter,
|
|
6
|
+
S3Cacher,
|
|
7
|
+
S3LimitedSeekableWriter,
|
|
8
|
+
S3Path,
|
|
9
|
+
S3PrefetchReader,
|
|
10
|
+
S3ShareCacheReader,
|
|
11
|
+
get_endpoint_url,
|
|
12
|
+
get_s3_client,
|
|
13
|
+
get_s3_session,
|
|
14
|
+
is_s3,
|
|
15
|
+
parse_s3_url,
|
|
16
|
+
s3_buffered_open,
|
|
17
|
+
s3_cached_open,
|
|
18
|
+
s3_concat,
|
|
19
|
+
s3_download,
|
|
20
|
+
s3_glob,
|
|
21
|
+
s3_glob_stat,
|
|
22
|
+
s3_iglob,
|
|
23
|
+
s3_load_content,
|
|
24
|
+
s3_lstat,
|
|
25
|
+
s3_makedirs,
|
|
26
|
+
s3_memory_open,
|
|
27
|
+
s3_open,
|
|
28
|
+
s3_path_join,
|
|
29
|
+
s3_pipe_open,
|
|
30
|
+
s3_prefetch_open,
|
|
31
|
+
s3_readlink,
|
|
32
|
+
s3_rename,
|
|
33
|
+
s3_share_cache_open,
|
|
34
|
+
s3_upload,
|
|
35
|
+
)
|
|
5
36
|
|
|
6
37
|
__all__ = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
38
|
+
"parse_s3_url",
|
|
39
|
+
"get_endpoint_url",
|
|
40
|
+
"get_s3_session",
|
|
41
|
+
"get_s3_client",
|
|
42
|
+
"s3_path_join",
|
|
43
|
+
"is_s3",
|
|
44
|
+
"s3_buffered_open",
|
|
45
|
+
"s3_cached_open",
|
|
46
|
+
"s3_memory_open",
|
|
47
|
+
"s3_pipe_open",
|
|
48
|
+
"s3_prefetch_open",
|
|
49
|
+
"s3_share_cache_open",
|
|
50
|
+
"s3_open",
|
|
51
|
+
"S3Cacher",
|
|
52
|
+
"S3BufferedWriter",
|
|
53
|
+
"S3LimitedSeekableWriter",
|
|
54
|
+
"S3PrefetchReader",
|
|
55
|
+
"S3ShareCacheReader",
|
|
56
|
+
"s3_upload",
|
|
57
|
+
"s3_download",
|
|
58
|
+
"s3_load_content",
|
|
59
|
+
"s3_readlink",
|
|
60
|
+
"s3_glob",
|
|
61
|
+
"s3_glob_stat",
|
|
62
|
+
"s3_iglob",
|
|
63
|
+
"s3_rename",
|
|
64
|
+
"s3_makedirs",
|
|
65
|
+
"s3_concat",
|
|
66
|
+
"s3_lstat",
|
|
67
|
+
"s3_access",
|
|
68
|
+
"s3_exists",
|
|
69
|
+
"s3_getmtime",
|
|
70
|
+
"s3_getsize",
|
|
71
|
+
"s3_isdir",
|
|
72
|
+
"s3_isfile",
|
|
73
|
+
"s3_listdir",
|
|
74
|
+
"s3_load_from",
|
|
75
|
+
"s3_hasbucket",
|
|
76
|
+
"s3_move",
|
|
77
|
+
"s3_remove",
|
|
78
|
+
"s3_scan",
|
|
79
|
+
"s3_scan_stat",
|
|
80
|
+
"s3_scandir",
|
|
81
|
+
"s3_stat",
|
|
82
|
+
"s3_unlink",
|
|
83
|
+
"s3_walk",
|
|
84
|
+
"s3_getmd5",
|
|
85
|
+
"s3_copy",
|
|
86
|
+
"s3_sync",
|
|
87
|
+
"s3_symlink",
|
|
88
|
+
"s3_islink",
|
|
89
|
+
"s3_save_as",
|
|
59
90
|
]
|
|
60
91
|
|
|
61
92
|
|
|
62
93
|
def s3_access(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'''
|
|
94
|
+
path: PathLike, mode: Access = Access.READ, followlinks: bool = False
|
|
95
|
+
) -> bool:
|
|
96
|
+
"""
|
|
67
97
|
Test if path has access permission described by mode
|
|
68
98
|
|
|
69
99
|
:param path: Given path
|
|
70
100
|
:param mode: access mode
|
|
71
101
|
:returns: bool, if the bucket of s3_url has read/write access.
|
|
72
|
-
|
|
102
|
+
"""
|
|
73
103
|
return S3Path(path).access(mode, followlinks)
|
|
74
104
|
|
|
75
105
|
|
|
76
106
|
def s3_exists(path: PathLike, followlinks: bool = False) -> bool:
|
|
77
|
-
|
|
107
|
+
"""
|
|
78
108
|
Test if s3_url exists
|
|
79
109
|
|
|
80
110
|
If the bucket of s3_url are not permitted to read, return False
|
|
81
111
|
|
|
82
112
|
:param path: Given path
|
|
83
113
|
:returns: True if s3_url exists, else False
|
|
84
|
-
|
|
114
|
+
"""
|
|
85
115
|
return S3Path(path).exists(followlinks)
|
|
86
116
|
|
|
87
117
|
|
|
88
118
|
def s3_getmtime(path: PathLike, follow_symlinks: bool = False) -> float:
|
|
89
|
-
|
|
90
|
-
Get last-modified time of the file on the given s3_url path
|
|
91
|
-
|
|
119
|
+
"""
|
|
120
|
+
Get last-modified time of the file on the given s3_url path
|
|
121
|
+
(in Unix timestamp format).
|
|
92
122
|
|
|
93
|
-
If
|
|
123
|
+
If the path is an existent directory, return the latest modified time of
|
|
124
|
+
all file in it. The mtime of empty directory is 1970-01-01 00:00:00
|
|
125
|
+
|
|
126
|
+
If s3_url is not an existent path, which means s3_exist(s3_url) returns False,
|
|
127
|
+
then raise S3FileNotFoundError
|
|
94
128
|
|
|
95
129
|
:param path: Given path
|
|
96
130
|
:returns: Last-modified time
|
|
97
131
|
:raises: S3FileNotFoundError, UnsupportedError
|
|
98
|
-
|
|
132
|
+
"""
|
|
99
133
|
return S3Path(path).getmtime(follow_symlinks)
|
|
100
134
|
|
|
101
135
|
|
|
102
136
|
def s3_getsize(path: PathLike, follow_symlinks: bool = False) -> int:
|
|
103
|
-
|
|
137
|
+
"""
|
|
104
138
|
Get file size on the given s3_url path (in bytes).
|
|
105
|
-
If the path in a directory, return the sum of all file size in it, including file in subdirectories (if exist).
|
|
106
|
-
The result excludes the size of directory itself. In other words, return 0 Byte on an empty directory path.
|
|
107
139
|
|
|
108
|
-
If
|
|
140
|
+
If the path in a directory, return the sum of all file size in it,
|
|
141
|
+
including file in subdirectories (if exist).
|
|
142
|
+
|
|
143
|
+
The result excludes the size of directory itself.
|
|
144
|
+
In other words, return 0 Byte on an empty directory path.
|
|
145
|
+
|
|
146
|
+
If s3_url is not an existent path, which means s3_exist(s3_url) returns False,
|
|
147
|
+
then raise S3FileNotFoundError
|
|
109
148
|
|
|
110
149
|
:param path: Given path
|
|
111
150
|
:returns: File size
|
|
112
151
|
:raises: S3FileNotFoundError, UnsupportedError
|
|
113
|
-
|
|
152
|
+
"""
|
|
114
153
|
return S3Path(path).getsize(follow_symlinks)
|
|
115
154
|
|
|
116
155
|
|
|
117
156
|
def s3_isdir(path: PathLike, followlinks: bool = False) -> bool:
|
|
118
|
-
|
|
157
|
+
"""
|
|
119
158
|
Test if an s3 url is directory
|
|
120
159
|
Specific procedures are as follows:
|
|
121
160
|
If there exists a suffix, of which ``os.path.join(s3_url, suffix)`` is a file
|
|
122
161
|
If the url is empty bucket or s3://
|
|
123
162
|
|
|
124
163
|
:param path: Given path
|
|
125
|
-
:param followlinks: whether followlinks is True or False, result is the same.
|
|
164
|
+
:param followlinks: whether followlinks is True or False, result is the same.
|
|
165
|
+
Because s3 symlink not support dir.
|
|
126
166
|
:returns: True if path is s3 directory, else False
|
|
127
|
-
|
|
167
|
+
"""
|
|
128
168
|
return S3Path(path).is_dir(followlinks)
|
|
129
169
|
|
|
130
170
|
|
|
131
171
|
def s3_isfile(path: PathLike, followlinks: bool = False) -> bool:
|
|
132
|
-
|
|
172
|
+
"""
|
|
133
173
|
Test if an s3_url is file
|
|
134
174
|
|
|
135
175
|
:param path: Given path
|
|
136
176
|
:returns: True if path is s3 file, else False
|
|
137
|
-
|
|
177
|
+
"""
|
|
138
178
|
return S3Path(path).is_file(followlinks)
|
|
139
179
|
|
|
140
180
|
|
|
141
181
|
def s3_listdir(path: PathLike, followlinks: bool = False) -> List[str]:
|
|
142
|
-
|
|
182
|
+
"""
|
|
143
183
|
Get all contents of given s3_url. The result is in ascending alphabetical order.
|
|
144
184
|
|
|
145
185
|
:param path: Given path
|
|
146
186
|
:returns: All contents have prefix of s3_url in ascending alphabetical order
|
|
147
187
|
:raises: S3FileNotFoundError, S3NotADirectoryError
|
|
148
|
-
|
|
188
|
+
"""
|
|
149
189
|
return S3Path(path).listdir(followlinks)
|
|
150
190
|
|
|
151
191
|
|
|
152
192
|
def s3_load_from(path: PathLike, followlinks: bool = False) -> BinaryIO:
|
|
153
|
-
|
|
193
|
+
"""Read all content in binary on specified path and write into memory
|
|
154
194
|
|
|
155
195
|
User should close the BinaryIO manually
|
|
156
196
|
|
|
157
197
|
:param path: Given path
|
|
158
198
|
:returns: BinaryIO
|
|
159
|
-
|
|
199
|
+
"""
|
|
160
200
|
return S3Path(path).load(followlinks)
|
|
161
201
|
|
|
162
202
|
|
|
163
203
|
def s3_hasbucket(path: PathLike) -> bool:
|
|
164
|
-
|
|
204
|
+
"""
|
|
165
205
|
Test if the bucket of s3_url exists
|
|
166
206
|
|
|
167
207
|
:param path: Given path
|
|
168
208
|
:returns: True if bucket of s3_url exists, else False
|
|
169
|
-
|
|
209
|
+
"""
|
|
170
210
|
return S3Path(path).hasbucket()
|
|
171
211
|
|
|
172
212
|
|
|
173
|
-
def s3_move(
|
|
174
|
-
|
|
175
|
-
'''
|
|
213
|
+
def s3_move(src_url: PathLike, dst_url: PathLike, overwrite: bool = True) -> None:
|
|
214
|
+
"""
|
|
176
215
|
Move file/directory path from src_url to dst_url
|
|
177
216
|
|
|
178
217
|
:param src_url: Given path
|
|
179
218
|
:param dst_url: Given destination path
|
|
180
219
|
:param overwrite: whether or not overwrite file when exists
|
|
181
|
-
|
|
220
|
+
"""
|
|
182
221
|
return S3Path(src_url).move(dst_url, overwrite)
|
|
183
222
|
|
|
184
223
|
|
|
185
224
|
def s3_remove(path: PathLike, missing_ok: bool = False) -> None:
|
|
186
|
-
|
|
187
|
-
Remove the file or directory on s3, `s3://` and `s3://bucket`
|
|
225
|
+
"""
|
|
226
|
+
Remove the file or directory on s3, `s3://` and `s3://bucket`
|
|
227
|
+
are not permitted to remove
|
|
188
228
|
|
|
189
229
|
:param path: Given path
|
|
190
|
-
:param missing_ok: if False and target file/directory not exists,
|
|
230
|
+
:param missing_ok: if False and target file/directory not exists,
|
|
231
|
+
raise S3FileNotFoundError
|
|
191
232
|
:raises: S3PermissionError, S3FileNotFoundError, UnsupportedError
|
|
192
|
-
|
|
233
|
+
"""
|
|
193
234
|
return S3Path(path).remove(missing_ok)
|
|
194
235
|
|
|
195
236
|
|
|
196
|
-
def s3_scan(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
237
|
+
def s3_scan(
|
|
238
|
+
path: PathLike, missing_ok: bool = True, followlinks: bool = False
|
|
239
|
+
) -> Iterator[str]:
|
|
240
|
+
"""
|
|
200
241
|
Iteratively traverse only files in given s3 directory, in alphabetical order.
|
|
201
242
|
Every iteration on generator yields a path string.
|
|
202
243
|
|
|
203
244
|
If s3_url is a file path, yields the file only
|
|
245
|
+
|
|
204
246
|
If s3_url is a non-existent path, return an empty generator
|
|
247
|
+
|
|
205
248
|
If s3_url is a bucket path, return all file paths in the bucket
|
|
249
|
+
|
|
206
250
|
If s3_url is an empty bucket, return an empty generator
|
|
207
|
-
|
|
251
|
+
|
|
252
|
+
If s3_url doesn't contain any bucket, which is s3_url == 's3://',
|
|
253
|
+
raise UnsupportedError. walk() on complete s3 is not supported in megfile
|
|
208
254
|
|
|
209
255
|
:param path: Given path
|
|
210
|
-
:param missing_ok: If False and there's no file in the directory,
|
|
256
|
+
:param missing_ok: If False and there's no file in the directory,
|
|
257
|
+
raise FileNotFoundError
|
|
211
258
|
:raises: UnsupportedError
|
|
212
259
|
:returns: A file path generator
|
|
213
|
-
|
|
260
|
+
"""
|
|
214
261
|
return S3Path(path).scan(missing_ok, followlinks)
|
|
215
262
|
|
|
216
263
|
|
|
217
264
|
def s3_scan_stat(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
'''
|
|
265
|
+
path: PathLike, missing_ok: bool = True, followlinks: bool = False
|
|
266
|
+
) -> Iterator[FileEntry]:
|
|
267
|
+
"""
|
|
222
268
|
Iteratively traverse only files in given directory, in alphabetical order.
|
|
223
269
|
Every iteration on generator yields a tuple of path string and file stat
|
|
224
270
|
|
|
225
271
|
:param path: Given path
|
|
226
|
-
:param missing_ok: If False and there's no file in the directory,
|
|
272
|
+
:param missing_ok: If False and there's no file in the directory,
|
|
273
|
+
raise FileNotFoundError
|
|
227
274
|
:raises: UnsupportedError
|
|
228
275
|
:returns: A file path generator
|
|
229
|
-
|
|
276
|
+
"""
|
|
230
277
|
return S3Path(path).scan_stat(missing_ok, followlinks)
|
|
231
278
|
|
|
232
279
|
|
|
233
|
-
def s3_scandir(path: PathLike,
|
|
234
|
-
|
|
235
|
-
'''
|
|
280
|
+
def s3_scandir(path: PathLike, followlinks: bool = False) -> Iterator[FileEntry]:
|
|
281
|
+
"""
|
|
236
282
|
Get all contents of given s3_url, the order of result is not guaranteed.
|
|
237
283
|
|
|
238
284
|
:param path: Given path
|
|
239
285
|
:returns: All contents have prefix of s3_url
|
|
240
286
|
:raises: S3FileNotFoundError, S3NotADirectoryError
|
|
241
|
-
|
|
287
|
+
"""
|
|
242
288
|
return S3Path(path).scandir(followlinks)
|
|
243
289
|
|
|
244
290
|
|
|
245
291
|
def s3_stat(path: PathLike, follow_symlinks=True) -> StatResult:
|
|
246
|
-
|
|
247
|
-
Get StatResult of s3_url file, including file size and mtime,
|
|
292
|
+
"""
|
|
293
|
+
Get StatResult of s3_url file, including file size and mtime,
|
|
294
|
+
referring to s3_getsize and s3_getmtime
|
|
248
295
|
|
|
249
|
-
If s3_url is not an existent path, which means s3_exist(s3_url) returns False,
|
|
250
|
-
|
|
296
|
+
If s3_url is not an existent path, which means s3_exist(s3_url) returns False,
|
|
297
|
+
then raise S3FileNotFoundError
|
|
298
|
+
|
|
299
|
+
If attempt to get StatResult of complete s3, such as s3_dir_url == 's3://',
|
|
300
|
+
raise S3BucketNotFoundError
|
|
251
301
|
|
|
252
302
|
:param path: Given path
|
|
253
303
|
:returns: StatResult
|
|
254
304
|
:raises: S3FileNotFoundError, S3BucketNotFoundError
|
|
255
|
-
|
|
305
|
+
"""
|
|
256
306
|
return S3Path(path).stat(follow_symlinks)
|
|
257
307
|
|
|
258
308
|
|
|
259
309
|
def s3_unlink(path: PathLike, missing_ok: bool = False) -> None:
|
|
260
|
-
|
|
310
|
+
"""
|
|
261
311
|
Remove the file on s3
|
|
262
312
|
|
|
263
313
|
:param path: Given path
|
|
264
|
-
:param missing_ok: if False and target file not exists,
|
|
314
|
+
:param missing_ok: if False and target file not exists,
|
|
315
|
+
raise S3FileNotFoundError
|
|
265
316
|
:raises: S3PermissionError, S3FileNotFoundError, S3IsADirectoryError
|
|
266
|
-
|
|
317
|
+
"""
|
|
267
318
|
return S3Path(path).unlink(missing_ok)
|
|
268
319
|
|
|
269
320
|
|
|
270
321
|
def s3_walk(
|
|
271
|
-
|
|
272
|
-
followlinks: bool = False
|
|
322
|
+
path: PathLike, followlinks: bool = False
|
|
273
323
|
) -> Iterator[Tuple[str, List[str], List[str]]]:
|
|
274
|
-
|
|
275
|
-
Iteratively traverse the given s3 directory, in top-bottom order.
|
|
324
|
+
"""
|
|
325
|
+
Iteratively traverse the given s3 directory, in top-bottom order.
|
|
326
|
+
In other words, firstly traverse parent directory, if subdirectories exist,
|
|
327
|
+
traverse the subdirectories in alphabetical order.
|
|
328
|
+
|
|
276
329
|
Every iteration on generator yields a 3-tuple: (root, dirs, files)
|
|
277
330
|
|
|
278
331
|
- root: Current s3 path;
|
|
279
|
-
- dirs: Name list of subdirectories in current directory.
|
|
280
|
-
|
|
332
|
+
- dirs: Name list of subdirectories in current directory.
|
|
333
|
+
The list is sorted by name in ascending alphabetical order;
|
|
334
|
+
- files: Name list of files in current directory.
|
|
335
|
+
The list is sorted by name in ascending alphabetical order;
|
|
281
336
|
|
|
282
337
|
If s3_url is a file path, return an empty generator
|
|
338
|
+
|
|
283
339
|
If s3_url is a non-existent path, return an empty generator
|
|
284
|
-
|
|
285
|
-
If s3_url is
|
|
286
|
-
|
|
340
|
+
|
|
341
|
+
If s3_url is a bucket path, bucket will be the top directory,
|
|
342
|
+
and will be returned at first iteration of generator
|
|
343
|
+
|
|
344
|
+
If s3_url is an empty bucket, only yield one 3-tuple
|
|
345
|
+
(notes: s3 doesn't have empty directory)
|
|
346
|
+
|
|
347
|
+
If s3_url doesn't contain any bucket, which is s3_url == 's3://',
|
|
348
|
+
raise UnsupportedError. walk() on complete s3 is not supported in megfile
|
|
287
349
|
|
|
288
350
|
:param path: Given path
|
|
289
|
-
:param followlinks: whether followlinks is True or False, result is the same.
|
|
351
|
+
:param followlinks: whether followlinks is True or False, result is the same.
|
|
352
|
+
Because s3 symlink not support dir.
|
|
290
353
|
:raises: UnsupportedError
|
|
291
354
|
:returns: A 3-tuple generator
|
|
292
|
-
|
|
355
|
+
"""
|
|
293
356
|
return S3Path(path).walk(followlinks)
|
|
294
357
|
|
|
295
358
|
|
|
296
359
|
def s3_getmd5(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
'''
|
|
360
|
+
path: PathLike, recalculate: bool = False, followlinks: bool = False
|
|
361
|
+
) -> str:
|
|
362
|
+
"""
|
|
301
363
|
Get md5 meta info in files that uploaded/copied via megfile
|
|
302
364
|
|
|
303
365
|
If meta info is lost or non-existent, return None
|
|
@@ -306,73 +368,78 @@ def s3_getmd5(
|
|
|
306
368
|
:param recalculate: calculate md5 in real-time or return s3 etag
|
|
307
369
|
:param followlinks: If is True, calculate md5 for real file
|
|
308
370
|
:returns: md5 meta info
|
|
309
|
-
|
|
371
|
+
"""
|
|
310
372
|
return S3Path(path).md5(recalculate, followlinks)
|
|
311
373
|
|
|
312
374
|
|
|
313
375
|
def s3_copy(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
376
|
+
src_url: PathLike,
|
|
377
|
+
dst_url: PathLike,
|
|
378
|
+
callback: Optional[Callable[[int], None]] = None,
|
|
379
|
+
followlinks: bool = False,
|
|
380
|
+
overwrite: bool = True,
|
|
381
|
+
) -> None:
|
|
382
|
+
"""File copy on S3
|
|
320
383
|
Copy content of file on `src_path` to `dst_path`.
|
|
321
|
-
It's caller's responsibility to ensure the s3_isfile(src_url)
|
|
384
|
+
It's caller's responsibility to ensure the s3_isfile(src_url) is True
|
|
322
385
|
|
|
323
386
|
:param src_url: Given path
|
|
324
387
|
:param dst_path: Target file path
|
|
325
|
-
:param callback: Called periodically during copy, and the input parameter is
|
|
388
|
+
:param callback: Called periodically during copy, and the input parameter is
|
|
389
|
+
the data size (in bytes) of copy since the last call
|
|
326
390
|
:param followlinks: False if regard symlink as file, else True
|
|
327
391
|
:param overwrite: whether or not overwrite file when exists, default is True
|
|
328
|
-
|
|
392
|
+
"""
|
|
329
393
|
return S3Path(src_url).copy(dst_url, callback, followlinks, overwrite)
|
|
330
394
|
|
|
331
395
|
|
|
332
396
|
def s3_sync(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
397
|
+
src_url: PathLike,
|
|
398
|
+
dst_url: PathLike,
|
|
399
|
+
followlinks: bool = False,
|
|
400
|
+
force: bool = False,
|
|
401
|
+
overwrite: bool = True,
|
|
402
|
+
) -> None:
|
|
403
|
+
"""
|
|
339
404
|
Copy file/directory on src_url to dst_url
|
|
340
405
|
|
|
341
406
|
:param src_url: Given path
|
|
342
407
|
:param dst_url: Given destination path
|
|
343
408
|
:param followlinks: False if regard symlink as file, else True
|
|
344
|
-
:param force: Sync file forcible, do not ignore same files,
|
|
409
|
+
:param force: Sync file forcible, do not ignore same files,
|
|
410
|
+
priority is higher than 'overwrite', default is False
|
|
345
411
|
:param overwrite: whether or not overwrite file when exists, default is True
|
|
346
|
-
|
|
412
|
+
"""
|
|
347
413
|
return S3Path(src_url).sync(dst_url, followlinks, force, overwrite)
|
|
348
414
|
|
|
349
415
|
|
|
350
416
|
def s3_symlink(src_path: PathLike, dst_path: PathLike) -> None:
|
|
351
|
-
|
|
417
|
+
"""
|
|
352
418
|
Create a symbolic link pointing to src_path named dst_path.
|
|
353
419
|
|
|
354
420
|
:param src_path: Given path
|
|
355
421
|
:param dst_path: Destination path
|
|
356
422
|
:raises: S3NameTooLongError, S3BucketNotFoundError, S3IsADirectoryError
|
|
357
|
-
|
|
423
|
+
"""
|
|
358
424
|
return S3Path(src_path).symlink(dst_path)
|
|
359
425
|
|
|
360
426
|
|
|
361
427
|
def s3_islink(path: PathLike) -> bool:
|
|
362
|
-
|
|
428
|
+
"""
|
|
363
429
|
Test whether a path is link
|
|
364
430
|
|
|
365
431
|
:param path: Given path
|
|
366
432
|
:returns: True if a path is link, else False
|
|
367
433
|
:raises: S3NotALinkError
|
|
368
|
-
|
|
434
|
+
"""
|
|
369
435
|
return S3Path(path).is_symlink()
|
|
370
436
|
|
|
371
437
|
|
|
372
438
|
def s3_save_as(file_object: BinaryIO, path: PathLike):
|
|
373
|
-
|
|
439
|
+
"""Write the opened binary stream to specified path,
|
|
440
|
+
but the stream won't be closed
|
|
374
441
|
|
|
375
442
|
:param path: Given path
|
|
376
443
|
:param file_object: Stream to be read
|
|
377
|
-
|
|
444
|
+
"""
|
|
378
445
|
return S3Path(path).save(file_object)
|