megfile 4.0.4__py3-none-any.whl → 4.1.0.post1__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/sftp_path.py CHANGED
@@ -116,10 +116,12 @@ def _patch_sftp_client_request(
116
116
  ssh_client = get_ssh_client(hostname, port, username, password, default_policy)
117
117
  ssh_client.close()
118
118
  atexit.unregister(ssh_client.close)
119
- ssh_key = f"ssh_client:{hostname},{port},{username},{password}"
119
+ ssh_key = f"ssh_client:{hostname},{port},{username},{password},{default_policy}"
120
120
  if thread_local.get(ssh_key):
121
121
  del thread_local[ssh_key]
122
- sftp_key = f"sftp_client:{hostname},{port},{username},{password}"
122
+ sftp_key = (
123
+ f"sftp_client:{hostname},{port},{username},{password},{default_policy}"
124
+ )
123
125
  if thread_local.get(sftp_key):
124
126
  del thread_local[sftp_key]
125
127
 
@@ -179,7 +181,7 @@ def get_sftp_client(
179
181
  :returns: sftp client
180
182
  """
181
183
  return thread_local(
182
- f"sftp_client:{hostname},{port},{username},{password}",
184
+ f"sftp_client:{hostname},{port},{username},{password},{default_policy}",
183
185
  _get_sftp_client,
184
186
  hostname,
185
187
  port,
@@ -219,7 +221,7 @@ def _get_ssh_client(
219
221
  ),
220
222
  os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
221
223
  )
222
- except Exception:
224
+ except Exception: # pragma: no cover
223
225
  _logger.warning(
224
226
  "Can't create file lock in '/tmp', "
225
227
  "please control the SFTP concurrency count by yourself."
@@ -252,7 +254,7 @@ def get_ssh_client(
252
254
  default_policy: Type[paramiko.MissingHostKeyPolicy] = paramiko.RejectPolicy,
253
255
  ) -> paramiko.SSHClient:
254
256
  return thread_local(
255
- f"ssh_client:{hostname},{port},{username},{password}",
257
+ f"ssh_client:{hostname},{port},{username},{password},{default_policy}",
256
258
  _get_ssh_client,
257
259
  hostname,
258
260
  port,
@@ -273,10 +275,12 @@ def get_ssh_session(
273
275
  ssh_client = get_ssh_client(hostname, port, username, password, default_policy)
274
276
  ssh_client.close()
275
277
  atexit.unregister(ssh_client.close)
276
- ssh_key = f"ssh_client:{hostname},{port},{username},{password}"
278
+ ssh_key = f"ssh_client:{hostname},{port},{username},{password},{default_policy}"
277
279
  if thread_local.get(ssh_key):
278
280
  del thread_local[ssh_key]
279
- sftp_key = f"sftp_client:{hostname},{port},{username},{password}"
281
+ sftp_key = (
282
+ f"sftp_client:{hostname},{port},{username},{password},{default_policy}"
283
+ )
280
284
  if thread_local.get(sftp_key):
281
285
  del thread_local[sftp_key]
282
286
 
@@ -530,8 +534,11 @@ class SftpPath(URIPath):
530
534
  glob_path = self.joinpath(pattern).path_with_protocol
531
535
 
532
536
  def _scandir(dirname: str) -> Iterator[Tuple[str, bool]]:
537
+ result = []
533
538
  for entry in self.from_path(dirname).scandir():
534
- yield entry.name, entry.is_dir()
539
+ result.append((entry.name, entry.is_dir()))
540
+ for name, is_dir in sorted(result):
541
+ yield name, is_dir
535
542
 
536
543
  def _exist(path: PathLike, followlinks: bool = False):
537
544
  return self.from_path(path).exists(followlinks=followlinks)
@@ -596,21 +603,18 @@ class SftpPath(URIPath):
596
603
 
597
604
  :returns: All contents have in the path in ascending alphabetical order
598
605
  """
599
- if not self.is_dir():
600
- raise NotADirectoryError(f"Not a directory: '{self.path_with_protocol}'")
601
- return sorted(self._client.listdir(self._real_path))
606
+ with self.scandir() as entries:
607
+ return sorted([entry.name for entry in entries])
602
608
 
603
609
  def iterdir(self) -> Iterator["SftpPath"]:
604
610
  """
605
- Get all contents of given sftp path.
606
- The result is in ascending alphabetical order.
611
+ Get all contents of given sftp path. The order of result is in arbitrary order.
607
612
 
608
- :returns: All contents have in the path in ascending alphabetical order
613
+ :returns: All contents have in the path.
609
614
  """
610
- if not self.is_dir():
611
- raise NotADirectoryError(f"Not a directory: '{self.path_with_protocol}'")
612
- for path in self.listdir():
613
- yield self.joinpath(path)
615
+ with self.scandir() as entries:
616
+ for entry in entries:
617
+ yield self.joinpath(entry.name)
614
618
 
615
619
  def load(self) -> BinaryIO:
616
620
  """Read all content on specified path and write into memory
@@ -807,20 +811,21 @@ class SftpPath(URIPath):
807
811
  FileNotFoundError("No match any file in: %r" % self.path_with_protocol),
808
812
  )
809
813
 
810
- def scandir(self) -> Iterator[FileEntry]:
814
+ def scandir(self) -> ContextIterator:
811
815
  """
812
816
  Get all content of given file path.
813
817
 
814
818
  :returns: An iterator contains all contents have prefix path
815
819
  """
816
- if not self.exists():
817
- raise FileNotFoundError("No such directory: %r" % self.path_with_protocol)
818
-
819
- if not self.is_dir():
820
- raise NotADirectoryError("Not a directory: %r" % self.path_with_protocol)
820
+ real_path = self._real_path
821
+ stat = self.stat(follow_symlinks=False)
822
+ if stat.is_symlink():
823
+ real_path = self.readlink()._real_path
824
+ elif not stat.is_dir():
825
+ raise NotADirectoryError(f"Not a directory: '{self.path_with_protocol}'")
821
826
 
822
827
  def create_generator():
823
- for name in self.listdir():
828
+ for name in self._client.listdir(real_path):
824
829
  current_path = self.joinpath(name)
825
830
  yield FileEntry(
826
831
  current_path.name,
@@ -917,7 +922,7 @@ class SftpPath(URIPath):
917
922
  path = self._client.normalize(self._real_path)
918
923
  return self._generate_path_object(path, resolve=True)
919
924
 
920
- def md5(self, recalculate: bool = False, followlinks: bool = True):
925
+ def md5(self, recalculate: bool = False, followlinks: bool = False):
921
926
  """
922
927
  Calculate the md5 value of the file
923
928
 
@@ -992,6 +997,7 @@ class SftpPath(URIPath):
992
997
  def open(
993
998
  self,
994
999
  mode: str = "r",
1000
+ *,
995
1001
  buffering=-1,
996
1002
  encoding: Optional[str] = None,
997
1003
  errors: Optional[str] = None,
@@ -1022,7 +1028,7 @@ class SftpPath(URIPath):
1022
1028
  ) # pytype: disable=wrong-arg-types
1023
1029
  return fileobj # pytype: disable=bad-return-type
1024
1030
 
1025
- def chmod(self, mode: int, follow_symlinks: bool = True):
1031
+ def chmod(self, mode: int, *, follow_symlinks: bool = True):
1026
1032
  """
1027
1033
  Change the file mode and permissions, like os.chmod().
1028
1034
 
megfile/smart.py CHANGED
@@ -285,8 +285,6 @@ def register_copy_func(
285
285
  dst_dict = _copy_funcs.get(src_protocol, {})
286
286
  dst_dict[dst_protocol] = copy_func
287
287
  _copy_funcs[src_protocol] = dst_dict
288
- except Exception as error:
289
- raise error
290
288
  else:
291
289
  raise ValueError(
292
290
  "Copy Function has already existed: {}->{}".format(
@@ -1081,13 +1079,14 @@ def smart_touch(path: PathLike):
1081
1079
  pass
1082
1080
 
1083
1081
 
1084
- def smart_getmd5(path: PathLike, recalculate: bool = False):
1082
+ def smart_getmd5(path: PathLike, recalculate: bool = False, followlinks: bool = False):
1085
1083
  """Get md5 value of file
1086
1084
 
1087
1085
  param path: File path
1088
1086
  param recalculate: calculate md5 in real-time or not return s3 etag when path is s3
1087
+ param followlinks: If is True, calculate md5 for real file
1089
1088
  """
1090
- return SmartPath(path).md5(recalculate=recalculate)
1089
+ return SmartPath(path).md5(recalculate=recalculate, followlinks=followlinks)
1091
1090
 
1092
1091
 
1093
1092
  _concat_funcs = {"s3": s3_concat, "sftp": sftp_concat}
megfile/stdio.py CHANGED
@@ -12,6 +12,7 @@ __all__ = [
12
12
  def stdio_open(
13
13
  path: PathLike,
14
14
  mode: str = "rb",
15
+ *,
15
16
  encoding: Optional[str] = None,
16
17
  errors: Optional[str] = None,
17
18
  **kwargs,
@@ -26,4 +27,4 @@ def stdio_open(
26
27
  :param mode: Only supports 'rb' and 'wb' now
27
28
  :return: STDReader, STDWriter
28
29
  """
29
- return StdioPath(path).open(mode, encoding, errors)
30
+ return StdioPath(path).open(mode, encoding=encoding, errors=errors)
megfile/stdio_path.py CHANGED
@@ -72,6 +72,7 @@ class StdioPath(BasePath):
72
72
  def open(
73
73
  self,
74
74
  mode: str = "rb",
75
+ *,
75
76
  encoding: Optional[str] = None,
76
77
  errors: Optional[str] = None,
77
78
  **kwargs,
megfile/version.py CHANGED
@@ -1 +1 @@
1
- VERSION = "4.0.4"
1
+ VERSION = "4.1.0.post1"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: megfile
3
- Version: 4.0.4
3
+ Version: 4.1.0.post1
4
4
  Summary: Megvii file operation library
5
5
  Author-email: megvii <megfile@megvii.com>
6
6
  Project-URL: Homepage, https://github.com/megvii-research/megfile
@@ -1,41 +1,41 @@
1
1
  megfile/__init__.py,sha256=7oEfu410CFKzDWZ9RjL5xEJ1gtkJkTfvPrL_7TWdJuY,7366
2
2
  megfile/cli.py,sha256=Y7ZyWsYmzMUjUrJ1Vz-WMWJQcpK-4og_5xyRzfKI91U,24957
3
3
  megfile/config.py,sha256=2MMj5QkhlDJQFZRbCQL2c9iDdeMAVctiaPszRBkg5vM,3988
4
- megfile/errors.py,sha256=KrzJFBgX7awoSJBADswCo4u6qbj-rcVQMN5It209Dvk,14333
5
- megfile/fs.py,sha256=bPGbapv41FzME87X3MhSNQRjNmHrI23FuFnjPT0ukQs,18239
6
- megfile/fs_path.py,sha256=K485rResPqL56m9oIkbBBCTrUkoKBWIP5EjhjbpTkIY,39141
7
- megfile/hdfs.py,sha256=JfqTTvMzTeDFAJ-uq5BU0sjFaE3qshlVZ0_5h9oImfA,13361
8
- megfile/hdfs_path.py,sha256=DbFuROHqlLo9o94N0HF1X83DMr7wKhZ9SR2mnKNVjyc,25739
4
+ megfile/errors.py,sha256=qSIiqiJmDLb2k1qKiTLdNQzj4VNgfM9bHkSClyCp1Kg,14385
5
+ megfile/fs.py,sha256=TJ0ifJ57IEL-gFgQhJD_WVEqmf28zC5kAvmH6c1QzbU,18240
6
+ megfile/fs_path.py,sha256=Hozl9LAJ8EMuSWBSZXGj2GNmPZ1sJp9PZs-7hPrLgm8,39341
7
+ megfile/hdfs.py,sha256=owXr4d3j1frCvlbhmhENcSBnKKDky5cJZzWLOF4ZJMo,13251
8
+ megfile/hdfs_path.py,sha256=OmUe3vA3Qoxnqtcq0Rs3ygBvzAtqUz3fGo8iP5sWneE,26058
9
9
  megfile/http.py,sha256=1nuGe-JbnwMFyV3s35CJxByED3uoRoS9y8Y8cSGP9Kw,3865
10
10
  megfile/http_path.py,sha256=yRIk-fNbrsY8rUS5KVOfocS_PS520dX5KOs8lImpLaY,14173
11
11
  megfile/interfaces.py,sha256=p4UvVZpeLx5djd6bqqDaygIx_s-_AxIVj-gudTch4JE,8467
12
- megfile/pathlike.py,sha256=vfuTBqSTIciRxkkqMfLfnBxWTEl9yns1yR8zgK4Raw0,31268
13
- megfile/s3.py,sha256=aVse1PsYchTkkMPUUW7GWfKOApvkl_Qh5pwNYdk7Ehc,16747
14
- megfile/s3_path.py,sha256=hhp0zkLfxe1MnKGlLnvPLi7mSYQirt81yGU8ToWl6r8,93576
15
- megfile/sftp.py,sha256=0ZnQlmhgvs7pYjFTcvvOyxTo2IUurE-hp1GN0hnIrdQ,26473
16
- megfile/sftp_path.py,sha256=LttyxwoDMb2nhY4b9qUAHTichrG6Rec8Q_xUTqC6VWI,43662
17
- megfile/smart.py,sha256=Ps8acPx6jeG1UJnRD8xL2aQjRp7IMW8sV6VFkMF0TQk,36910
12
+ megfile/pathlike.py,sha256=3Hnw-fn6RcIe9iPrJt00QdHSA--UfDyxnVBuZ_ymYYQ,31278
13
+ megfile/s3.py,sha256=abBxnI7RIyn7n7qjGszP1VruYd6Gi9I8QnUOvsHkx1Y,16325
14
+ megfile/s3_path.py,sha256=w9_I3BMbLTmu4WCa0W0O0NnFkOHS0CQ-9fvtViL-2iU,93565
15
+ megfile/sftp.py,sha256=uBcLQs-j6Q-q-sWAdd-pgi5Qmb_kq7boJM-0sCfcNO0,26540
16
+ megfile/sftp_path.py,sha256=Wz4VcQ0pBUuWDGMSxPpPbutrT09mnY6jZNiAqTi5tO4,43840
17
+ megfile/smart.py,sha256=xkNVEa3DAThM4zJf3aoHJg_t8PQeVv9yz66GhGIdhpA,36974
18
18
  megfile/smart_path.py,sha256=Bqg95T2-XZrRXWhH7GT-jMCYzD7i1SIXdczQxtOxiPs,7583
19
- megfile/stdio.py,sha256=C_cGID_npthpwoPcsJMMEqqbVUPUnDxxJV9jLY2_D7c,635
20
- megfile/stdio_path.py,sha256=L8ODNIwO79UIv13YYc2OTr6f4XTv4ZPyvBeRk83-AjA,2700
21
- megfile/version.py,sha256=hJ-Qyt0gNnGNOAUMy6dMT2dsePu73CM3Gc3e0kxG4hQ,19
19
+ megfile/stdio.py,sha256=ZwxsnJNJYIT7Iyg5pIw4qiyH8bszG6oAhEJuR-hXGG4,658
20
+ megfile/stdio_path.py,sha256=cxaDr8rtisTPnN-rjtaEpqQnshwiqwXFUJBM9xWY7Cg,2711
21
+ megfile/version.py,sha256=0T8ZzQ_dcDIRsR27VgeThkcTcJi4fE4WvZ8Me4aXAwc,25
22
22
  megfile/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- megfile/lib/base_prefetch_reader.py,sha256=6Dy2ZwlowqAvyUUa7bpQLCKOclmmUDhqEF-_CDDp0Og,13100
24
- megfile/lib/combine_reader.py,sha256=nKGAug29lOpNIZuLKu7_qVrJJRpXL_J4jxLglWbGJ1w,4808
23
+ megfile/lib/base_prefetch_reader.py,sha256=oSiQq6wlV9DADQapkf3Up3-86zl6QrtusVu93MAt1KE,12848
24
+ megfile/lib/combine_reader.py,sha256=Kp2wEloOUpTlIU7dve87MBpSzmIM-F9OtpTawAjFkiU,4828
25
25
  megfile/lib/compare.py,sha256=n_dtLxgoskYnsIZMKdKmVhQoVn8qYUrUhkS1JH2_X3o,2170
26
26
  megfile/lib/compat.py,sha256=SynEeHluys3tCK-lb_1oV3o_ft83yZvunqM_AjibLgE,207
27
27
  megfile/lib/fnmatch.py,sha256=4MvGzEahMRA-u8Z7mxaD-Yw1idOwBoJJpVywQy29jwY,4162
28
- megfile/lib/glob.py,sha256=aTK2aFyFobUs0W4deB4iASgtuq6DAE1jILmcAiP8Cb4,9840
28
+ megfile/lib/glob.py,sha256=1u0j_DoqT7VmTUsDAdcKhPbr4XOwIBpOkCnyAFEGw1I,9633
29
29
  megfile/lib/hdfs_prefetch_reader.py,sha256=yCNpcXcTiC2SHKHC-Qp50KQx1ObSLmOgwNUKlG-4ADg,2131
30
30
  megfile/lib/hdfs_tools.py,sha256=4K-OdMYFFSLBGmDzjatioHvuZuUbKVy7ACeJl-l0HLQ,435
31
31
  megfile/lib/http_prefetch_reader.py,sha256=OjP5pdWK_e1QiFIt2xmflceLnrz3S7B7ePBZFK-OwQE,4558
32
32
  megfile/lib/joinpath.py,sha256=gaPNtBi8fzd5LZNyZp5zrHzaybcqKJ1xlntGmVNyFEM,929
33
33
  megfile/lib/lazy_handler.py,sha256=bE7RGt1x_xYWMgGAvHr7dwEt52qy-D3z90X3oyCvE6g,1875
34
34
  megfile/lib/s3_buffered_writer.py,sha256=kXvz1bdoaVIxjnEQeg4dxEzAXMYNrk-5uIMww86ty00,7860
35
- megfile/lib/s3_cached_handler.py,sha256=X8PdeRC-BY6eSmOO5f2BeyjTPxyEwNtHgmAm9VgmDR4,1426
36
- megfile/lib/s3_limited_seekable_writer.py,sha256=mUeoTS98LHluwDN7zxdCVcsjOGBT1bOYV8nRvi9QMGE,6212
37
- megfile/lib/s3_memory_handler.py,sha256=4uzBzz2jfRI_u6jl0CpOGAhpNJhDQo18FSAweauCUFs,4136
38
- megfile/lib/s3_pipe_handler.py,sha256=dm7NnZd1Ym5ABS1GvOQtoCJEO_CB8e6p4sUhLiid0go,3622
35
+ megfile/lib/s3_cached_handler.py,sha256=MkNt6AAapd5x8BH2gnW5_S0cLofN-mshEdb0qSoLho8,1426
36
+ megfile/lib/s3_limited_seekable_writer.py,sha256=joVcjoTx48jataXAwEqOI3toRxxO3-XQRvyWHtJ23lQ,6232
37
+ megfile/lib/s3_memory_handler.py,sha256=_2JCLbbPUuIGGCeUEuSRZ-mdDRtGow2ofgtAQwzru4s,4136
38
+ megfile/lib/s3_pipe_handler.py,sha256=QKhcjXWkedM4-eX0BhZVmkmCjawfyBJfYzmGFUclO8w,3642
39
39
  megfile/lib/s3_prefetch_reader.py,sha256=R37-y_L9l8IKJhpT8HwBrZEbo2X72vCqEV6fvqPCBug,4437
40
40
  megfile/lib/s3_share_cache_reader.py,sha256=LVWKxHdHo0_zUIW4o8yqNvplqqwezUPeYEt02Vj-WNM,3754
41
41
  megfile/lib/shadow_handler.py,sha256=TntewlvIW9ZxCfmqASDQREHoiZ8v42faOe9sovQYQz0,2779
@@ -53,10 +53,10 @@ scripts/benchmark/code/s3fs_read.py,sha256=XiTA-qrYblUs-jQWXSnvNg5Wo722C_g47aMMf
53
53
  scripts/benchmark/code/s3fs_write.py,sha256=gdXKkWXYGjLJlRT_J64pJN85XvRg3bZexcAJQEMXwtw,402
54
54
  scripts/benchmark/code/smart_open_read.py,sha256=SA02jHwS9Y31yFtV9CoJcfND5dR0eA_HsGmGNUrpQls,515
55
55
  scripts/benchmark/code/smart_open_write.py,sha256=jDxFJdY97yNH889jz3pawBoei3yaqy8pEMvC_ymHFtM,537
56
- megfile-4.0.4.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
57
- megfile-4.0.4.dist-info/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
58
- megfile-4.0.4.dist-info/METADATA,sha256=ZOXOJNvkRh_LaCknY7VU_qS2KM6LNJf3MZVN6Pygsg0,9573
59
- megfile-4.0.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
60
- megfile-4.0.4.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
61
- megfile-4.0.4.dist-info/top_level.txt,sha256=fVg49lk5B9L7jyfWUXWxb0DDSuw5pbr0OU62Tvx8J8M,44
62
- megfile-4.0.4.dist-info/RECORD,,
56
+ megfile-4.1.0.post1.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
57
+ megfile-4.1.0.post1.dist-info/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
58
+ megfile-4.1.0.post1.dist-info/METADATA,sha256=McvjueS05XMnfNKJMjzNz6w5Oj5KK27DgJkYRm8q6hE,9579
59
+ megfile-4.1.0.post1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
60
+ megfile-4.1.0.post1.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
61
+ megfile-4.1.0.post1.dist-info/top_level.txt,sha256=fVg49lk5B9L7jyfWUXWxb0DDSuw5pbr0OU62Tvx8J8M,44
62
+ megfile-4.1.0.post1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5