megfile 2.2.5a3__py3-none-any.whl → 2.2.6a1__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/cli.py CHANGED
@@ -4,13 +4,14 @@ import shutil
4
4
  import sys
5
5
  import time
6
6
  from concurrent.futures import ThreadPoolExecutor
7
+ from functools import partial
7
8
 
8
9
  import click
9
10
  from tqdm import tqdm
10
11
 
11
12
  from megfile.interfaces import FileEntry
12
13
  from megfile.lib.glob import get_non_glob_dir, has_magic
13
- from megfile.smart import smart_copy, smart_getmd5, smart_getmtime, smart_getsize, smart_glob, smart_glob_stat, smart_isdir, smart_isfile, smart_makedirs, smart_move, smart_open, smart_path_join, smart_remove, smart_rename, smart_scan_stat, smart_scandir, smart_stat, smart_sync, smart_sync_with_progress, smart_touch, smart_unlink
14
+ from megfile.smart import _smart_sync_single_file, smart_copy, smart_getmd5, smart_getmtime, smart_getsize, smart_glob_stat, smart_isdir, smart_isfile, smart_makedirs, smart_move, smart_open, smart_path_join, smart_remove, smart_rename, smart_scan_stat, smart_scandir, smart_stat, smart_sync, smart_sync_with_progress, smart_touch, smart_unlink
14
15
  from megfile.smart_path import SmartPath
15
16
  from megfile.utils import get_human_size
16
17
  from megfile.version import VERSION
@@ -32,34 +33,36 @@ def safe_cli(): # pragma: no cover
32
33
  click.echo(f"\n[{type(e).__name__}] {e}", err=True)
33
34
 
34
35
 
35
- def get_echo_path(file_stat, base_path: str = ""):
36
+ def get_echo_path(file_stat, base_path: str = "", full_path: bool = False):
36
37
  if base_path == file_stat.path:
37
38
  path = file_stat.name
39
+ elif full_path:
40
+ path = file_stat.path
38
41
  else:
39
42
  path = os.path.relpath(file_stat.path, start=base_path)
40
43
  return path
41
44
 
42
45
 
43
- def simple_echo(file_stat, base_path: str = ""):
44
- click.echo(get_echo_path(file_stat, base_path))
46
+ def simple_echo(file_stat, base_path: str = "", full_path: bool = False):
47
+ click.echo(get_echo_path(file_stat, base_path, full_path))
45
48
 
46
49
 
47
- def long_echo(file_stat, base_path: str = ""):
50
+ def long_echo(file_stat, base_path: str = "", full_path: bool = False):
48
51
  click.echo(
49
52
  '%12d %s %s' % (
50
53
  file_stat.stat.size,
51
54
  time.strftime(
52
55
  "%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
53
- get_echo_path(file_stat, base_path)))
56
+ get_echo_path(file_stat, base_path, full_path)))
54
57
 
55
58
 
56
- def human_echo(file_stat, base_path: str = ""):
59
+ def human_echo(file_stat, base_path: str = "", full_path: bool = False):
57
60
  click.echo(
58
61
  '%10s %s %s' % (
59
62
  get_human_size(file_stat.stat.size),
60
63
  time.strftime(
61
64
  "%Y-%m-%d %H:%M:%S", time.localtime(file_stat.stat.mtime)),
62
- get_echo_path(file_stat, base_path)))
65
+ get_echo_path(file_stat, base_path, full_path)))
63
66
 
64
67
 
65
68
  def smart_list_stat(path):
@@ -91,9 +94,11 @@ def smart_list_stat(path):
91
94
  help='Displays file sizes in human readable format.')
92
95
  def ls(path: str, long: bool, recursive: bool, human_readable: bool):
93
96
  base_path = path
97
+ full_path = False
94
98
  if has_magic(path):
95
99
  scan_func = smart_glob_stat
96
100
  base_path = get_non_glob_dir(path)
101
+ full_path = True
97
102
  elif recursive:
98
103
  scan_func = smart_scan_stat
99
104
  else:
@@ -107,7 +112,7 @@ def ls(path: str, long: bool, recursive: bool, human_readable: bool):
107
112
  echo_func = simple_echo
108
113
 
109
114
  for file_stat in scan_func(path):
110
- echo_func(file_stat, base_path)
115
+ echo_func(file_stat, base_path, full_path=full_path)
111
116
 
112
117
 
113
118
  @cli.command(
@@ -264,65 +269,81 @@ def rm(path: str, recursive: bool):
264
269
  '--force',
265
270
  is_flag=True,
266
271
  help='Copy files forcely, ignore same files.')
272
+ @click.option('-q', '--quiet', is_flag=True, help='Not show any progress log.')
267
273
  def sync(
268
274
  src_path: str, dst_path: str, progress_bar: bool, worker: int,
269
- force: bool):
275
+ force: bool, quiet: bool):
270
276
  with ThreadPoolExecutor(max_workers=worker) as executor:
271
277
  if has_magic(src_path):
272
- root_dir = get_non_glob_dir(src_path)
273
- path_stats = []
274
- for dir_or_file in smart_glob(src_path, recursive=True,
275
- missing_ok=True):
276
- path_stats.extend(list(smart_scan_stat(dir_or_file)))
278
+ src_root_path = get_non_glob_dir(src_path)
279
+
280
+ def scan_func(path):
281
+ for glob_file_entry in smart_glob_stat(path):
282
+ if glob_file_entry.is_file():
283
+ yield glob_file_entry
284
+ else:
285
+ for file_entry in smart_scan_stat(glob_file_entry.path,
286
+ followlinks=True):
287
+ yield file_entry
288
+ else:
289
+ src_root_path = src_path
290
+ scan_func = partial(smart_scan_stat, followlinks=True)
291
+
292
+ if progress_bar and not quiet:
293
+ print('building progress bar', end='\r')
294
+ file_entries = []
295
+ total_count = total_size = 0
296
+ for total_count, file_entry in enumerate(scan_func(src_path),
297
+ start=1):
298
+ if total_count > 1024 * 128:
299
+ file_entries = []
300
+ else:
301
+ file_entries.append(file_entry)
302
+ total_size += file_entry.stat.size
303
+ print(
304
+ f'building progress bar, find {total_count} files',
305
+ end='\r')
306
+
307
+ if not file_entries:
308
+ file_entries = scan_func(src_path)
309
+ else:
310
+ total_count = total_size = None
311
+ file_entries = scan_func(src_path)
277
312
 
278
- if progress_bar:
279
- tbar = tqdm(total=len(path_stats), ascii=True)
280
- sbar = tqdm(
281
- unit='B', ascii=True, unit_scale=True, unit_divisor=1024)
313
+ if quiet:
314
+ callback = callback_after_copy_file = None
315
+ else:
316
+ tbar = tqdm(total=total_count, ascii=True)
317
+ sbar = tqdm(
318
+ unit='B',
319
+ ascii=True,
320
+ unit_scale=True,
321
+ unit_divisor=1024,
322
+ total=total_size)
282
323
 
283
- def callback(_filename: str, length: int):
284
- sbar.update(length)
324
+ def callback(_filename: str, length: int):
325
+ sbar.update(length)
285
326
 
286
- def callback_after_copy_file(src_file_path, dst_file_path):
287
- tbar.update(1)
327
+ def callback_after_copy_file(src_file_path, dst_file_path):
328
+ tbar.update(1)
288
329
 
289
- smart_sync(
290
- root_dir,
291
- dst_path,
330
+ for file_entry in file_entries:
331
+ executor.submit(
332
+ _smart_sync_single_file,
333
+ dict(
334
+ src_root_path=src_root_path,
335
+ dst_root_path=dst_path,
336
+ src_file_path=file_entry.path,
292
337
  callback=callback,
293
- callback_after_copy_file=callback_after_copy_file,
294
- src_file_stats=path_stats,
295
- map_func=executor.map,
296
- force=force,
297
338
  followlinks=True,
298
- )
299
-
300
- tbar.close()
301
- sbar.close()
302
- else:
303
- smart_sync(
304
- root_dir,
305
- dst_path,
306
- src_file_stats=path_stats,
307
- map_func=executor.map,
339
+ callback_after_copy_file=callback_after_copy_file,
308
340
  force=force,
309
- followlinks=True,
310
- )
311
- else:
312
- if progress_bar:
313
- smart_sync_with_progress(
314
- src_path,
315
- dst_path,
316
- followlinks=True,
317
- map_func=executor.map,
318
- force=force)
319
- else:
320
- smart_sync(
321
- src_path,
322
- dst_path,
323
- followlinks=True,
324
- map_func=executor.map,
325
- force=force)
341
+ ))
342
+ if not quiet:
343
+ tbar.close()
344
+ if progress_bar:
345
+ sbar.update(sbar.total - sbar.n)
346
+ sbar.close()
326
347
 
327
348
 
328
349
  @cli.command(short_help="Make the path if it doesn't already exist.")
megfile/errors.py CHANGED
@@ -110,7 +110,7 @@ def s3_should_retry(error: Exception) -> bool:
110
110
  if isinstance(error, botocore.exceptions.ClientError):
111
111
  return client_error_code(error) in (
112
112
  '500', '501', '502', '503', 'InternalError', 'ServiceUnavailable',
113
- 'SlowDown')
113
+ 'SlowDown', 'ContextCanceled')
114
114
  return False
115
115
 
116
116
 
@@ -52,11 +52,13 @@ class S3BufferedWriter(Writable):
52
52
  block_size: int = DEFAULT_BLOCK_SIZE,
53
53
  max_block_size: int = DEFAULT_MAX_BLOCK_SIZE,
54
54
  max_buffer_size: int = DEFAULT_MAX_BUFFER_SIZE,
55
- max_workers: Optional[int] = None):
55
+ max_workers: Optional[int] = None,
56
+ profile_name: Optional[str] = None):
56
57
 
57
58
  self._bucket = bucket
58
59
  self._key = key
59
60
  self._client = s3_client
61
+ self._profile_name = profile_name
60
62
 
61
63
  self._block_size = block_size
62
64
  self._max_block_size = max_block_size
@@ -86,7 +88,9 @@ class S3BufferedWriter(Writable):
86
88
 
87
89
  @property
88
90
  def name(self) -> str:
89
- return 's3://%s/%s' % (self._bucket, self._key)
91
+ return 's3%s://%s/%s' % (
92
+ f"+{self._profile_name}" if self._profile_name else "",
93
+ self._bucket, self._key)
90
94
 
91
95
  @property
92
96
  def mode(self) -> str:
@@ -17,7 +17,8 @@ class S3CachedHandler(S3MemoryHandler):
17
17
  *,
18
18
  s3_client,
19
19
  cache_path: Optional[str] = None,
20
- remove_cache_when_open: bool = True):
20
+ remove_cache_when_open: bool = True,
21
+ profile_name: Optional[str] = None):
21
22
 
22
23
  assert mode in ('rb', 'wb', 'ab', 'rb+', 'wb+', 'ab+')
23
24
 
@@ -25,6 +26,7 @@ class S3CachedHandler(S3MemoryHandler):
25
26
  self._key = key
26
27
  self._mode = mode
27
28
  self._client = s3_client
29
+ self._profile_name = profile_name
28
30
 
29
31
  if cache_path is None:
30
32
  cache_path = generate_cache_path(self.name)
@@ -29,7 +29,8 @@ class S3LimitedSeekableWriter(Seekable, S3BufferedWriter):
29
29
  tail_block_size: Optional[int] = None,
30
30
  max_block_size: int = DEFAULT_MAX_BLOCK_SIZE,
31
31
  max_buffer_size: int = DEFAULT_MAX_BUFFER_SIZE,
32
- max_workers: Optional[int] = None):
32
+ max_workers: Optional[int] = None,
33
+ profile_name: Optional[str] = None):
33
34
 
34
35
  super().__init__(
35
36
  bucket,
@@ -38,7 +39,8 @@ class S3LimitedSeekableWriter(Seekable, S3BufferedWriter):
38
39
  block_size=block_size,
39
40
  max_block_size=max_block_size,
40
41
  max_buffer_size=max_buffer_size,
41
- max_workers=max_workers)
42
+ max_workers=max_workers,
43
+ profile_name=profile_name)
42
44
 
43
45
  self._head_block_size = head_block_size or block_size
44
46
  self._tail_block_size = tail_block_size or block_size
@@ -8,7 +8,14 @@ from megfile.interfaces import Readable, Seekable, Writable
8
8
 
9
9
  class S3MemoryHandler(Readable, Seekable, Writable):
10
10
 
11
- def __init__(self, bucket: str, key: str, mode: str, *, s3_client):
11
+ def __init__(
12
+ self,
13
+ bucket: str,
14
+ key: str,
15
+ mode: str,
16
+ *,
17
+ s3_client,
18
+ profile_name: Optional[str] = None):
12
19
 
13
20
  assert mode in ('rb', 'wb', 'ab', 'rb+', 'wb+', 'ab+')
14
21
 
@@ -16,13 +23,16 @@ class S3MemoryHandler(Readable, Seekable, Writable):
16
23
  self._key = key
17
24
  self._mode = mode
18
25
  self._client = s3_client
26
+ self._profile_name = profile_name
19
27
 
20
28
  self._fileobj = BytesIO()
21
29
  self._download_fileobj()
22
30
 
23
31
  @property
24
32
  def name(self) -> str:
25
- return 's3://%s/%s' % (self._bucket, self._key)
33
+ return 's3%s://%s/%s' % (
34
+ f"+{self._profile_name}" if self._profile_name else "",
35
+ self._bucket, self._key)
26
36
 
27
37
  @property
28
38
  def mode(self) -> str:
@@ -33,7 +33,8 @@ class S3PipeHandler(Readable, Writable):
33
33
  mode: str,
34
34
  *,
35
35
  s3_client,
36
- join_thread: bool = True):
36
+ join_thread: bool = True,
37
+ profile_name: Optional[str] = None):
37
38
 
38
39
  assert mode in ('rb', 'wb')
39
40
 
@@ -43,6 +44,7 @@ class S3PipeHandler(Readable, Writable):
43
44
  self._client = s3_client
44
45
  self._join_thread = join_thread
45
46
  self._offset = 0
47
+ self._profile_name = profile_name
46
48
 
47
49
  self._exc = None
48
50
  self._pipe = os.pipe()
@@ -59,7 +61,9 @@ class S3PipeHandler(Readable, Writable):
59
61
 
60
62
  @property
61
63
  def name(self) -> str:
62
- return 's3://%s/%s' % (self._bucket, self._key)
64
+ return 's3%s://%s/%s' % (
65
+ f"+{self._profile_name}" if self._profile_name else "",
66
+ self._bucket, self._key)
63
67
 
64
68
  @property
65
69
  def mode(self) -> str:
@@ -34,11 +34,13 @@ class S3PrefetchReader(BasePrefetchReader):
34
34
  block_capacity: int = DEFAULT_BLOCK_CAPACITY,
35
35
  block_forward: Optional[int] = None,
36
36
  max_retries: int = 10,
37
- max_workers: Optional[int] = None):
37
+ max_workers: Optional[int] = None,
38
+ profile_name: Optional[str] = None):
38
39
 
39
40
  self._bucket = bucket
40
41
  self._key = key
41
42
  self._client = s3_client
43
+ self._profile_name = profile_name
42
44
 
43
45
  super().__init__(
44
46
  block_size=block_size,
@@ -68,7 +70,9 @@ class S3PrefetchReader(BasePrefetchReader):
68
70
 
69
71
  @property
70
72
  def name(self) -> str:
71
- return 's3://%s/%s' % (self._bucket, self._key)
73
+ return 's3%s://%s/%s' % (
74
+ f"+{self._profile_name}" if self._profile_name else "",
75
+ self._bucket, self._key)
72
76
 
73
77
  def _fetch_response(
74
78
  self, start: Optional[int] = None,
@@ -34,7 +34,8 @@ class S3ShareCacheReader(S3PrefetchReader):
34
34
  block_forward: Optional[int] = None,
35
35
  max_retries: int = 10,
36
36
  cache_key: str = 'lru',
37
- max_workers: Optional[int] = None):
37
+ max_workers: Optional[int] = None,
38
+ profile_name: Optional[str] = None):
38
39
 
39
40
  self._cache_key = cache_key
40
41
 
@@ -47,6 +48,7 @@ class S3ShareCacheReader(S3PrefetchReader):
47
48
  block_forward=block_forward,
48
49
  max_retries=max_retries,
49
50
  max_workers=max_workers,
51
+ profile_name=profile_name,
50
52
  )
51
53
 
52
54
  def _get_block_forward(
megfile/s3_path.py CHANGED
@@ -598,7 +598,8 @@ def s3_prefetch_open(
598
598
  s3_client=client,
599
599
  max_retries=max_retries,
600
600
  max_workers=max_concurrency,
601
- block_size=max_block_size)
601
+ block_size=max_block_size,
602
+ profile_name=s3_url._profile_name)
602
603
 
603
604
 
604
605
  @_s3_binary_mode
@@ -649,7 +650,8 @@ def s3_share_cache_open(
649
650
  s3_client=client,
650
651
  max_retries=max_retries,
651
652
  max_workers=max_concurrency,
652
- block_size=max_block_size)
653
+ block_size=max_block_size,
654
+ profile_name=s3_url._profile_name)
653
655
 
654
656
 
655
657
  @_s3_binary_mode
@@ -696,7 +698,12 @@ def s3_pipe_open(
696
698
  cache_key='s3_filelike_client',
697
699
  profile_name=s3_url._profile_name)
698
700
  return S3PipeHandler(
699
- bucket, key, mode, s3_client=client, join_thread=join_thread)
701
+ bucket,
702
+ key,
703
+ mode,
704
+ s3_client=client,
705
+ join_thread=join_thread,
706
+ profile_name=s3_url._profile_name)
700
707
 
701
708
 
702
709
  @_s3_binary_mode
@@ -737,7 +744,12 @@ def s3_cached_open(
737
744
  cache_key='s3_filelike_client',
738
745
  profile_name=s3_url._profile_name)
739
746
  return S3CachedHandler(
740
- bucket, key, mode, s3_client=client, cache_path=cache_path)
747
+ bucket,
748
+ key,
749
+ mode,
750
+ s3_client=client,
751
+ cache_path=cache_path,
752
+ profile_name=s3_url._profile_name)
741
753
 
742
754
 
743
755
  @_s3_binary_mode
@@ -792,9 +804,19 @@ def s3_buffered_open(
792
804
 
793
805
  if 'a' in mode or '+' in mode:
794
806
  if cache_path is None:
795
- return S3MemoryHandler(bucket, key, mode, s3_client=client)
807
+ return S3MemoryHandler(
808
+ bucket,
809
+ key,
810
+ mode,
811
+ s3_client=client,
812
+ profile_name=s3_url._profile_name)
796
813
  return S3CachedHandler(
797
- bucket, key, mode, s3_client=client, cache_path=cache_path)
814
+ bucket,
815
+ key,
816
+ mode,
817
+ s3_client=client,
818
+ cache_path=cache_path,
819
+ profile_name=s3_url._profile_name)
798
820
 
799
821
  if mode == 'rb':
800
822
  # A rough conversion algorithm to align 2 types of Reader / Writer parameters
@@ -813,7 +835,8 @@ def s3_buffered_open(
813
835
  max_retries=max_retries,
814
836
  max_workers=max_concurrency,
815
837
  block_size=block_size,
816
- block_forward=block_forward)
838
+ block_forward=block_forward,
839
+ profile_name=s3_url._profile_name)
817
840
  else:
818
841
  reader = S3PrefetchReader(
819
842
  bucket,
@@ -823,7 +846,8 @@ def s3_buffered_open(
823
846
  max_workers=max_concurrency,
824
847
  block_capacity=block_capacity,
825
848
  block_forward=block_forward,
826
- block_size=block_size)
849
+ block_size=block_size,
850
+ profile_name=s3_url._profile_name)
827
851
  if buffered:
828
852
  reader = io.BufferedReader(reader) # pytype: disable=wrong-arg-types
829
853
  return reader
@@ -835,7 +859,8 @@ def s3_buffered_open(
835
859
  s3_client=client,
836
860
  max_workers=max_concurrency,
837
861
  max_buffer_size=max_buffer_size,
838
- block_size=block_size)
862
+ block_size=block_size,
863
+ profile_name=s3_url._profile_name)
839
864
  else:
840
865
  writer = S3BufferedWriter(
841
866
  bucket,
@@ -843,7 +868,8 @@ def s3_buffered_open(
843
868
  s3_client=client,
844
869
  max_workers=max_concurrency,
845
870
  max_buffer_size=max_buffer_size,
846
- block_size=block_size)
871
+ block_size=block_size,
872
+ profile_name=s3_url._profile_name)
847
873
  if buffered:
848
874
  writer = io.BufferedWriter(writer) # pytype: disable=wrong-arg-types
849
875
  return writer
@@ -880,7 +906,8 @@ def s3_memory_open(
880
906
  config=config,
881
907
  cache_key='s3_filelike_client',
882
908
  profile_name=s3_url._profile_name)
883
- return S3MemoryHandler(bucket, key, mode, s3_client=client)
909
+ return S3MemoryHandler(
910
+ bucket, key, mode, s3_client=client, profile_name=s3_url._profile_name)
884
911
 
885
912
 
886
913
  s3_open = s3_buffered_open
megfile/sftp_path.py CHANGED
@@ -1,7 +1,9 @@
1
1
  import atexit
2
+ import fcntl
2
3
  import hashlib
3
4
  import io
4
5
  import os
6
+ import random
5
7
  import shlex
6
8
  import socket
7
9
  import subprocess
@@ -43,6 +45,7 @@ SFTP_PASSWORD = "SFTP_PASSWORD"
43
45
  SFTP_PRIVATE_KEY_PATH = "SFTP_PRIVATE_KEY_PATH"
44
46
  SFTP_PRIVATE_KEY_TYPE = "SFTP_PRIVATE_KEY_TYPE"
45
47
  SFTP_PRIVATE_KEY_PASSWORD = "SFTP_PRIVATE_KEY_PASSWORD"
48
+ SFTP_MAX_UNAUTH_CONN = "SFTP_MAX_UNAUTH_CONN"
46
49
  MAX_RETRIES = 10
47
50
  DEFAULT_SSH_CONNECT_TIMEOUT = 5
48
51
  DEFAULT_SSH_KEEPALIVE_INTERVAL = 15
@@ -194,6 +197,20 @@ def _get_ssh_client(
194
197
 
195
198
  ssh_client = paramiko.SSHClient()
196
199
  ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
200
+ max_unauth_connections = int(os.getenv(SFTP_MAX_UNAUTH_CONN, 10))
201
+ try:
202
+ fd = os.open(
203
+ os.path.join(
204
+ '/tmp',
205
+ f'megfile-sftp-{hostname}-{random.randint(1, max_unauth_connections)}'
206
+ ), os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
207
+ except Exception:
208
+ _logger.warning(
209
+ "Can't create file lock in '/tmp', please control the SFTP concurrency count by yourself."
210
+ )
211
+ fd = None
212
+ if fd:
213
+ fcntl.flock(fd, fcntl.LOCK_EX)
197
214
  ssh_client.connect(
198
215
  hostname=hostname,
199
216
  username=username,
@@ -203,6 +220,9 @@ def _get_ssh_client(
203
220
  auth_timeout=DEFAULT_SSH_CONNECT_TIMEOUT,
204
221
  banner_timeout=DEFAULT_SSH_CONNECT_TIMEOUT,
205
222
  )
223
+ if fd:
224
+ fcntl.flock(fd, fcntl.LOCK_UN)
225
+ os.close(fd)
206
226
  atexit.register(ssh_client.close)
207
227
  return ssh_client
208
228
 
megfile/version.py CHANGED
@@ -1 +1 @@
1
- VERSION = "2.2.5a3"
1
+ VERSION = "2.2.6a1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: megfile
3
- Version: 2.2.5a3
3
+ Version: 2.2.6a1
4
4
  Summary: Megvii file operation library
5
5
  Home-page: https://github.com/megvii-research/megfile
6
6
  Author: megvii
@@ -1,6 +1,6 @@
1
1
  megfile/__init__.py,sha256=Qsi3XNP_0XYoSol-1AGutZqo0rfBnzaiZ-HVXll4fB0,5721
2
- megfile/cli.py,sha256=Elv8Dvyvy0l8tXuzuw8GAfhUuZgnbxsndgIKQU98ltc,13701
3
- megfile/errors.py,sha256=NBpcxnsy5bvhlaTol8eIB8dwC54y-XqAGroS5wjk9AY,11934
2
+ megfile/cli.py,sha256=m6nqGc_vjA68SMv0NsqM-R5RpnZNczA4JI4Gt_mcFPw,14743
3
+ megfile/errors.py,sha256=IDqfdz0WjCwvV1Zp8N9iKFE8Y0nrYBH6c7_4EW_CJaM,11953
4
4
  megfile/fs.py,sha256=LtrzQsyZgogTJeoRFz4L52gxx0jByzRBLkpWYpvkp5I,11819
5
5
  megfile/fs_path.py,sha256=JkY8qGIIboK5MK2rSagYEvnu5FTzmk9OHXIhTO7BjeY,38767
6
6
  megfile/http.py,sha256=a3oAuARSSaIU8VMx86Mui0N5Vh-EI0AoHnwxRU5DSMU,2032
@@ -8,14 +8,14 @@ megfile/http_path.py,sha256=9X9klm6CtEfu4V0_LUWtSXC8JRYiNjVAJjdzEBfxUa8,9272
8
8
  megfile/interfaces.py,sha256=h3tWE8hVt5S-HopaMAX6lunPJ97vzhv6jH_2HubcDNc,6219
9
9
  megfile/pathlike.py,sha256=WpP8zWSOAcAfYrD65hZS08UEi4_iCoEMs2xvfFMwZvY,29264
10
10
  megfile/s3.py,sha256=7XZSWjcSY-hoLhLH9dtfyRpokfYH9raTO_Mf69RjpEs,12560
11
- megfile/s3_path.py,sha256=IADdIluSY2x6k1r8YVB3yO_uwbrqyTJwTEYxgA9DRB8,87722
11
+ megfile/s3_path.py,sha256=1bxhf8-Lg29oFB6BFbIQGDvKvSIE7ZS-YORHbe6kOiM,88409
12
12
  megfile/sftp.py,sha256=CZYv1WKL0d_vuJ5aPgMhm0W8uskzaO5zbYGhGwt_mQs,12771
13
- megfile/sftp_path.py,sha256=P3NIL-4Wd143Rnnh2c3Ai2r2nc_EGoVNg4hpoHCoVvA,49865
13
+ megfile/sftp_path.py,sha256=DG-X79bcPc1hikZ_PNha3K_ber8bqjx-KnW3jZG8iCw,50529
14
14
  megfile/smart.py,sha256=JH5zed90eQchS8GNQ7mbXvif-pNKjPjvnadMazKfQMs,33278
15
15
  megfile/smart_path.py,sha256=Y0UFh4J2ccydRY2W-wX2ubaf9zzJx1M2nf-VLBGe4mk,6749
16
16
  megfile/stdio.py,sha256=yRhlfUA2DHi3bq-9cXsSlbLCnHvS_zvglO2IYYyPsGc,707
17
17
  megfile/stdio_path.py,sha256=eQulTXUwHvUKA-5PKCGfVNiEPkJhG9YtVhtU58OcmoM,2873
18
- megfile/version.py,sha256=aeVQFfrw1apC4vP0iZO-mQFJ_DqNJuocadFBeKDoDqc,21
18
+ megfile/version.py,sha256=s1UlNdCKmZ0EggJzQ2Wu1Nz0xneCzoLAvSAoUlQHunY,21
19
19
  megfile/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  megfile/lib/base_prefetch_reader.py,sha256=SjrBffHVgvJnYtr8HNqiOozP9OJRYS37Eu1KQcZu1Z8,13221
21
21
  megfile/lib/combine_reader.py,sha256=XFSqEY5A5X5Uf7eQ6AXAzrvNteESSXvKNVPktGjo3KY,4546
@@ -26,22 +26,22 @@ megfile/lib/glob.py,sha256=7i9dIput9rI9JIPyTZX-JDmFS7IP_THlX1k-35foAfw,9732
26
26
  megfile/lib/http_prefetch_reader.py,sha256=YDtQXRX-yxyaFzqI_CL3X73-Idkdz1aPIDL29uY77zw,3326
27
27
  megfile/lib/joinpath.py,sha256=D4Px6-lnDDpYs1LMUHkTIGqMPJQ0oCBGfTzREs373iU,929
28
28
  megfile/lib/lazy_handler.py,sha256=f1rip2_T57vVo0WRNXve2bAa4LArvVheMfQg1S0vFzg,1915
29
- megfile/lib/s3_buffered_writer.py,sha256=AGjCNQ1X16kjFbEJouavkO6ykmlAtfVKBPAD-yYwAT0,6934
30
- megfile/lib/s3_cached_handler.py,sha256=e4KamTLMIPKa96yp7HGF05wDl2Yfoizz9pBrz-uAQ5w,1322
31
- megfile/lib/s3_limited_seekable_writer.py,sha256=NSBh5cZCCtwZM0DTwfPkpOA_h0NXd9-6qjasOby5zxc,6037
32
- megfile/lib/s3_memory_handler.py,sha256=jLBA5HVuI-UBPYMYN-B8iX_VGr8bC9brAqY-KbEGrtw,3725
33
- megfile/lib/s3_pipe_handler.py,sha256=38x8oPrxlXVWqMgDOqScPj0Pt2w2cQFSNoTK27EtBSw,3384
34
- megfile/lib/s3_prefetch_reader.py,sha256=yhY-ucs6BW1XgNDLC0xQ2lMrGVhc3Nk3hHr6GBfjRDA,4050
35
- megfile/lib/s3_share_cache_reader.py,sha256=QyZvzVpTswgiXv-E8QhV_jFdQjCBxVcgbgybXo6d1cM,3771
29
+ megfile/lib/s3_buffered_writer.py,sha256=9wiOXY7MgHrP7ulrN-QE2GcfwTfsTBniMxL9iDulpFw,7107
30
+ megfile/lib/s3_cached_handler.py,sha256=xuWiThi6pJtGL_ErSBmcu8rDv1XyXNmEhiFBnRF4NWU,1412
31
+ megfile/lib/s3_limited_seekable_writer.py,sha256=Dz4e5Gu-b9BoIzGHh5AAEkIGGUEB9Hg7MDToHS_05gk,6124
32
+ megfile/lib/s3_memory_handler.py,sha256=6Tj89xzc8z-FycVggGpjF_8lEbPsqRVB6undZwWsugo,3971
33
+ megfile/lib/s3_pipe_handler.py,sha256=hG8sEajO9dv9bLTeXsERxDioHHhzi4t8NC61lSbYk94,3557
34
+ megfile/lib/s3_prefetch_reader.py,sha256=vRZfFSV7bNliBrdD3cxgUrYSzLrgPPrzBT8zJMeAB8Q,4223
35
+ megfile/lib/s3_share_cache_reader.py,sha256=bPnD82lqrXtdLMegxyY15MzbWUHXuX0KKGtJHNOWD-w,3860
36
36
  megfile/lib/shadow_handler.py,sha256=IbFyTw107t-yWH0cGrDjAJX-CS3xeEr77_PTGsnSgk4,2683
37
37
  megfile/lib/stdio_handler.py,sha256=QDWtcZxz-hzi-rqQUiSlR3NrihX1fjK_Rj9T2mdTFEg,2044
38
38
  megfile/lib/url.py,sha256=VbQLjo0s4AaV0iSk66BcjI68aUTcN9zBZ5x6-cM4Qvs,103
39
39
  megfile/utils/__init__.py,sha256=qdX8FF_dYFKwp1BIWx3JeSGd91s7AKUDSEpDv9tORcM,9162
40
40
  megfile/utils/mutex.py,sha256=-2KH3bNovKRd9zvsXq9n3bWM7rQdoG9hO7tUPxVG_Po,2538
41
- megfile-2.2.5a3.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
42
- megfile-2.2.5a3.dist-info/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
43
- megfile-2.2.5a3.dist-info/METADATA,sha256=t3-ccaCpUl41YRoKG-y2r9Z_weNE4Al3v7pTvLLZ-_A,10744
44
- megfile-2.2.5a3.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
45
- megfile-2.2.5a3.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
46
- megfile-2.2.5a3.dist-info/top_level.txt,sha256=i3rMgdU1ZAJekAceojhA-bkm3749PzshtRmLTbeLUPQ,8
47
- megfile-2.2.5a3.dist-info/RECORD,,
41
+ megfile-2.2.6a1.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
42
+ megfile-2.2.6a1.dist-info/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
43
+ megfile-2.2.6a1.dist-info/METADATA,sha256=rDzvBg6_knLWNEyWEX5k_afGpOcGkjNDk3XQoho_O7g,10744
44
+ megfile-2.2.6a1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
45
+ megfile-2.2.6a1.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
46
+ megfile-2.2.6a1.dist-info/top_level.txt,sha256=i3rMgdU1ZAJekAceojhA-bkm3749PzshtRmLTbeLUPQ,8
47
+ megfile-2.2.6a1.dist-info/RECORD,,