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.
Files changed (55) hide show
  1. docs/conf.py +2 -4
  2. megfile/__init__.py +394 -203
  3. megfile/cli.py +258 -238
  4. megfile/config.py +25 -21
  5. megfile/errors.py +124 -114
  6. megfile/fs.py +174 -140
  7. megfile/fs_path.py +462 -354
  8. megfile/hdfs.py +133 -101
  9. megfile/hdfs_path.py +290 -236
  10. megfile/http.py +15 -14
  11. megfile/http_path.py +111 -107
  12. megfile/interfaces.py +70 -65
  13. megfile/lib/base_prefetch_reader.py +84 -65
  14. megfile/lib/combine_reader.py +12 -12
  15. megfile/lib/compare.py +17 -13
  16. megfile/lib/compat.py +1 -5
  17. megfile/lib/fnmatch.py +29 -30
  18. megfile/lib/glob.py +46 -54
  19. megfile/lib/hdfs_prefetch_reader.py +40 -25
  20. megfile/lib/hdfs_tools.py +1 -3
  21. megfile/lib/http_prefetch_reader.py +69 -46
  22. megfile/lib/joinpath.py +5 -5
  23. megfile/lib/lazy_handler.py +7 -3
  24. megfile/lib/s3_buffered_writer.py +58 -51
  25. megfile/lib/s3_cached_handler.py +13 -14
  26. megfile/lib/s3_limited_seekable_writer.py +37 -28
  27. megfile/lib/s3_memory_handler.py +34 -30
  28. megfile/lib/s3_pipe_handler.py +24 -25
  29. megfile/lib/s3_prefetch_reader.py +71 -52
  30. megfile/lib/s3_share_cache_reader.py +37 -24
  31. megfile/lib/shadow_handler.py +7 -3
  32. megfile/lib/stdio_handler.py +9 -8
  33. megfile/lib/url.py +3 -3
  34. megfile/pathlike.py +259 -228
  35. megfile/s3.py +220 -153
  36. megfile/s3_path.py +977 -802
  37. megfile/sftp.py +190 -156
  38. megfile/sftp_path.py +540 -450
  39. megfile/smart.py +397 -330
  40. megfile/smart_path.py +100 -105
  41. megfile/stdio.py +10 -9
  42. megfile/stdio_path.py +32 -35
  43. megfile/utils/__init__.py +73 -54
  44. megfile/utils/mutex.py +11 -14
  45. megfile/version.py +1 -1
  46. {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/METADATA +5 -8
  47. megfile-3.1.2.dist-info/RECORD +55 -0
  48. {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/WHEEL +1 -1
  49. scripts/convert_results_to_sarif.py +45 -78
  50. scripts/generate_file.py +140 -64
  51. megfile-3.1.1.dist-info/RECORD +0 -55
  52. {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/LICENSE +0 -0
  53. {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/LICENSE.pyre +0 -0
  54. {megfile-3.1.1.dist-info → megfile-3.1.2.dist-info}/entry_points.txt +0 -0
  55. {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 S3BufferedWriter, S3Cacher, S3LimitedSeekableWriter, S3Path, S3PrefetchReader, S3ShareCacheReader, get_endpoint_url, get_s3_client, get_s3_session, is_s3, parse_s3_url, s3_buffered_open, s3_cached_open, s3_concat, s3_download, s3_glob, s3_glob_stat, s3_iglob, s3_load_content, s3_lstat, s3_makedirs, s3_memory_open, s3_open, s3_path_join, s3_pipe_open, s3_prefetch_open, s3_readlink, s3_rename, s3_share_cache_open, s3_upload
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
- 'parse_s3_url',
8
- 'get_endpoint_url',
9
- 'get_s3_session',
10
- 'get_s3_client',
11
- 's3_path_join',
12
- 'is_s3',
13
- 's3_buffered_open',
14
- 's3_cached_open',
15
- 's3_memory_open',
16
- 's3_pipe_open',
17
- 's3_prefetch_open',
18
- 's3_share_cache_open',
19
- 's3_open',
20
- 'S3Cacher',
21
- 'S3BufferedWriter',
22
- 'S3LimitedSeekableWriter',
23
- 'S3PrefetchReader',
24
- 'S3ShareCacheReader',
25
- 's3_upload',
26
- 's3_download',
27
- 's3_load_content',
28
- 's3_readlink',
29
- 's3_glob',
30
- 's3_glob_stat',
31
- 's3_iglob',
32
- 's3_rename',
33
- 's3_makedirs',
34
- 's3_concat',
35
- 's3_lstat',
36
- 's3_access',
37
- 's3_exists',
38
- 's3_getmtime',
39
- 's3_getsize',
40
- 's3_isdir',
41
- 's3_isfile',
42
- 's3_listdir',
43
- 's3_load_from',
44
- 's3_hasbucket',
45
- 's3_move',
46
- 's3_remove',
47
- 's3_scan',
48
- 's3_scan_stat',
49
- 's3_scandir',
50
- 's3_stat',
51
- 's3_unlink',
52
- 's3_walk',
53
- 's3_getmd5',
54
- 's3_copy',
55
- 's3_sync',
56
- 's3_symlink',
57
- 's3_islink',
58
- 's3_save_as',
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
- path: PathLike,
64
- mode: Access = Access.READ,
65
- followlinks: bool = False) -> bool:
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 (in Unix timestamp format).
91
- If the path is an existent directory, return the latest modified time of all file in it. The mtime of empty directory is 1970-01-01 00:00:00
119
+ """
120
+ Get last-modified time of the file on the given s3_url path
121
+ (in Unix timestamp format).
92
122
 
93
- If s3_url is not an existent path, which means s3_exist(s3_url) returns False, then raise S3FileNotFoundError
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 s3_url is not an existent path, which means s3_exist(s3_url) returns False, then raise S3FileNotFoundError
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. Because s3 symlink not support dir.
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
- '''Read all content in binary on specified path and write into memory
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
- src_url: PathLike, dst_url: PathLike, overwrite: bool = True) -> None:
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` are not permitted to remove
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, raise S3FileNotFoundError
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(path: PathLike,
197
- missing_ok: bool = True,
198
- followlinks: bool = False) -> Iterator[str]:
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
- If s3_url doesn't contain any bucket, which is s3_url == 's3://', raise UnsupportedError. walk() on complete s3 is not supported in megfile
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, raise FileNotFoundError
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
- path: PathLike,
219
- missing_ok: bool = True,
220
- followlinks: bool = False) -> Iterator[FileEntry]:
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, raise FileNotFoundError
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
- followlinks: bool = False) -> Iterator[FileEntry]:
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, referring to s3_getsize and s3_getmtime
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, then raise S3FileNotFoundError
250
- If attempt to get StatResult of complete s3, such as s3_dir_url == 's3://', raise S3BucketNotFoundError
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, raise S3FileNotFoundError
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
- path: PathLike,
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. In other words, firstly traverse parent directory, if subdirectories exist, traverse the subdirectories in alphabetical 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. The list is sorted by name in ascending alphabetical order;
280
- - files: Name list of files in current directory. The list is sorted by name in ascending alphabetical order;
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
- If s3_url is a bucket path, bucket will be the top directory, and will be returned at first iteration of generator
285
- If s3_url is an empty bucket, only yield one 3-tuple (notes: s3 doesn't have empty directory)
286
- If s3_url doesn't contain any bucket, which is s3_url == 's3://', raise UnsupportedError. walk() on complete s3 is not supported in megfile
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. Because s3 symlink not support dir.
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
- path: PathLike,
298
- recalculate: bool = False,
299
- followlinks: bool = False) -> str:
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
- src_url: PathLike,
315
- dst_url: PathLike,
316
- callback: Optional[Callable[[int], None]] = None,
317
- followlinks: bool = False,
318
- overwrite: bool = True) -> None:
319
- ''' File copy on S3
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) == True
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 the data size (in bytes) of copy since the last call
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
- src_url: PathLike,
334
- dst_url: PathLike,
335
- followlinks: bool = False,
336
- force: bool = False,
337
- overwrite: bool = True) -> None:
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, priority is higher than 'overwrite', default is False
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
- '''Write the opened binary stream to specified path, but the stream won't be closed
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)