megfile 4.1.8.post1__py3-none-any.whl → 4.2.1__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
@@ -70,17 +70,16 @@ def cli(debug, log_level):
70
70
  """
71
71
  options["debug"] = debug
72
72
  options["log_level"] = log_level or ("DEBUG" if debug else "INFO")
73
+ if not debug:
74
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
73
75
  set_log_level(options["log_level"])
74
76
 
75
77
 
76
78
  def safe_cli(): # pragma: no cover
77
- debug = options.get("debug", False)
78
- if not debug:
79
- signal.signal(signal.SIGINT, signal.SIG_DFL)
80
79
  try:
81
80
  cli()
82
81
  except Exception as e:
83
- if debug:
82
+ if options.get("debug", False):
84
83
  raise
85
84
  else:
86
85
  click.echo(f"\n[{type(e).__name__}] {e}", err=True)
megfile/s3_path.py CHANGED
@@ -605,6 +605,8 @@ def _s3_glob_stat_single_path(
605
605
  for content in resp.get("Contents", []):
606
606
  path = s3_path_join(f"{protocol}://", bucket, content["Key"])
607
607
  if not search_dir and pattern.match(path):
608
+ if path.endswith("/"):
609
+ continue
608
610
  yield FileEntry(S3Path(path).name, path, _make_stat(content))
609
611
  dirname = os.path.dirname(path)
610
612
  while dirname not in dirnames and dirname != top_dir:
@@ -1674,15 +1676,18 @@ class S3Path(URIPath):
1674
1676
  :returns: True if path is s3 file, else False
1675
1677
  """
1676
1678
  s3_url = self.path_with_protocol
1679
+ bucket, key = parse_s3_url(s3_url)
1680
+ if not bucket or not key or key.endswith("/"):
1681
+ # s3://, s3:///key, s3://bucket, s3://bucket/prefix/
1682
+ return False
1683
+
1677
1684
  if followlinks:
1678
1685
  try:
1679
1686
  s3_url = self.readlink().path_with_protocol
1687
+ bucket, key = parse_s3_url(s3_url)
1680
1688
  except S3NotALinkError:
1681
1689
  pass
1682
- bucket, key = parse_s3_url(s3_url)
1683
- if not bucket or not key or key.endswith("/"):
1684
- # s3://, s3:///key, s3://bucket, s3://bucket/prefix/
1685
- return False
1690
+
1686
1691
  try:
1687
1692
  self._client.head_object(Bucket=bucket, Key=key)
1688
1693
  except Exception as error:
@@ -1827,18 +1832,18 @@ class S3Path(URIPath):
1827
1832
  )
1828
1833
  if not key:
1829
1834
  raise UnsupportedError("Remove bucket", self.path_with_protocol)
1830
- if not self.exists():
1831
- if missing_ok:
1832
- return
1833
- raise S3FileNotFoundError(
1834
- "No such file or directory: %r" % self.path_with_protocol
1835
- )
1836
1835
 
1837
1836
  client = self._client
1837
+ if self.is_file():
1838
+ try:
1839
+ with raise_s3_error(self.path_with_protocol):
1840
+ client.delete_object(Bucket=bucket, Key=key)
1841
+ except S3FileNotFoundError:
1842
+ if not missing_ok:
1843
+ raise
1844
+ return
1845
+
1838
1846
  with raise_s3_error(self.path_with_protocol):
1839
- if self.is_file():
1840
- client.delete_object(Bucket=bucket, Key=key)
1841
- return
1842
1847
  prefix = _become_prefix(key)
1843
1848
  total_count, error_count = 0, 0
1844
1849
  for resp in _list_objects_recursive(client, bucket, prefix):
@@ -1889,6 +1894,10 @@ class S3Path(URIPath):
1889
1894
  % (self.path_with_protocol, total_count, error_count)
1890
1895
  )
1891
1896
  raise S3UnknownError(Exception(error_msg), self.path_with_protocol)
1897
+ if total_count == 0 and not missing_ok:
1898
+ raise S3FileNotFoundError(
1899
+ "No such file or directory: %r" % self.path_with_protocol
1900
+ )
1892
1901
 
1893
1902
  def rename(self, dst_path: PathLike, overwrite: bool = True) -> "S3Path":
1894
1903
  """
@@ -1960,6 +1969,7 @@ class S3Path(URIPath):
1960
1969
  )
1961
1970
 
1962
1971
  prefix = _become_prefix(key)
1972
+ protocol = self._protocol_with_profile
1963
1973
  client = self._client
1964
1974
 
1965
1975
  def suppress_error_callback(e):
@@ -1970,13 +1980,13 @@ class S3Path(URIPath):
1970
1980
  with raise_s3_error(self.path_with_protocol, suppress_error_callback):
1971
1981
  for resp in _list_objects_recursive(client, bucket, prefix):
1972
1982
  for content in resp.get("Contents", []):
1973
- full_path = s3_path_join(
1974
- f"{self._protocol_with_profile}://", bucket, content["Key"]
1975
- )
1983
+ if content["Key"].endswith("/"):
1984
+ continue
1985
+ path = s3_path_join(f"{protocol}://", bucket, content["Key"])
1976
1986
 
1977
1987
  if followlinks:
1978
1988
  try:
1979
- origin_path = self.from_path(full_path).readlink()
1989
+ origin_path = self.from_path(path).readlink()
1980
1990
  yield FileEntry(
1981
1991
  origin_path.name,
1982
1992
  origin_path.path_with_protocol,
@@ -1986,9 +1996,7 @@ class S3Path(URIPath):
1986
1996
  except S3NotALinkError:
1987
1997
  pass
1988
1998
 
1989
- yield FileEntry(
1990
- S3Path(full_path).name, full_path, _make_stat(content)
1991
- )
1999
+ yield FileEntry(S3Path(path).name, path, _make_stat(content))
1992
2000
 
1993
2001
  return _create_missing_ok_generator(
1994
2002
  create_generator(),
@@ -2016,17 +2024,15 @@ class S3Path(URIPath):
2016
2024
  # we need to wrap the iterator in another function
2017
2025
  def create_generator() -> Iterator[FileEntry]:
2018
2026
  prefix = _become_prefix(key)
2027
+ protocol = self._protocol_with_profile
2019
2028
  client = self._client
2020
2029
 
2021
- def generate_s3_path(protocol: str, bucket: str, key: str) -> str:
2022
- return "%s://%s/%s" % (protocol, bucket, key)
2023
-
2024
2030
  if not bucket and not key: # list buckets
2025
2031
  response = client.list_buckets()
2026
2032
  for content in response["Buckets"]:
2027
2033
  yield FileEntry(
2028
2034
  content["Name"],
2029
- f"{self._protocol_with_profile}://{content['Name']}",
2035
+ f"{protocol}://{content['Name']}",
2030
2036
  StatResult(
2031
2037
  ctime=content["CreationDate"].timestamp(),
2032
2038
  isdir=True,
@@ -2039,21 +2045,17 @@ class S3Path(URIPath):
2039
2045
  for common_prefix in resp.get("CommonPrefixes", []):
2040
2046
  yield FileEntry(
2041
2047
  common_prefix["Prefix"][len(prefix) : -1],
2042
- generate_s3_path(
2043
- self._protocol_with_profile,
2044
- bucket,
2045
- common_prefix["Prefix"],
2046
- ),
2048
+ f"{protocol}://{bucket}/{common_prefix['Prefix']}",
2047
2049
  StatResult(isdir=True, extra=common_prefix),
2048
2050
  )
2049
2051
  for content in resp.get("Contents", []):
2050
- src_url = generate_s3_path(
2051
- self._protocol_with_profile, bucket, content["Key"]
2052
- )
2052
+ if content["Key"].endswith("/"):
2053
+ continue
2054
+ path = f"{protocol}://{bucket}/{content['Key']}"
2053
2055
  yield FileEntry( # pytype: disable=wrong-arg-types
2054
2056
  content["Key"][len(prefix) :],
2055
- src_url,
2056
- _make_stat_without_metadata(content, self.from_path(src_url)),
2057
+ path,
2058
+ _make_stat_without_metadata(content, self.from_path(path)),
2057
2059
  )
2058
2060
 
2059
2061
  def missing_ok_generator():
@@ -2220,6 +2222,8 @@ class S3Path(URIPath):
2220
2222
  for common_prefix in resp.get("CommonPrefixes", []):
2221
2223
  dirs.append(common_prefix["Prefix"][:-1])
2222
2224
  for content in resp.get("Contents", []):
2225
+ if content["Key"].endswith("/"):
2226
+ continue
2223
2227
  files.append(content["Key"])
2224
2228
 
2225
2229
  dirs = sorted(dirs)
megfile/version.py CHANGED
@@ -1 +1 @@
1
- VERSION = "4.1.8.post1"
1
+ VERSION = "4.2.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: megfile
3
- Version: 4.1.8.post1
3
+ Version: 4.2.1
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,5 +1,5 @@
1
1
  megfile/__init__.py,sha256=7oEfu410CFKzDWZ9RjL5xEJ1gtkJkTfvPrL_7TWdJuY,7366
2
- megfile/cli.py,sha256=iwwlwVNu_yXgqnaURPHqGPrx1WeReqN0zi9C4rqK5Ag,29178
2
+ megfile/cli.py,sha256=VxY0__M19Ti_S7ZIozp9l0FxvdLwdd6eQL-wfpYOi_0,29160
3
3
  megfile/config.py,sha256=2MMj5QkhlDJQFZRbCQL2c9iDdeMAVctiaPszRBkg5vM,3988
4
4
  megfile/errors.py,sha256=aw4BX-pU1uj0-dNc6Tq-IeSwK_PWJNi2ZL5ZcRSo7aQ,14739
5
5
  megfile/fs.py,sha256=KMEqAE35alpcxiy6du5nPFYcaorhUM_kPJMah3q76ng,19160
@@ -11,14 +11,14 @@ megfile/http_path.py,sha256=08OmzmRMyLSyq1Yr1K2HbzexesURJrIoA6AibwYzUiA,13844
11
11
  megfile/interfaces.py,sha256=p4UvVZpeLx5djd6bqqDaygIx_s-_AxIVj-gudTch4JE,8467
12
12
  megfile/pathlike.py,sha256=3Hnw-fn6RcIe9iPrJt00QdHSA--UfDyxnVBuZ_ymYYQ,31278
13
13
  megfile/s3.py,sha256=abBxnI7RIyn7n7qjGszP1VruYd6Gi9I8QnUOvsHkx1Y,16325
14
- megfile/s3_path.py,sha256=4vKdn5RupvSMYelYznCMDpE1t-87H3iwgzY4iZHWmIE,93519
14
+ megfile/s3_path.py,sha256=NKOJLxy1gxdOc-jdEvxNl45tham5un8YWmZC-CZXHuU,93663
15
15
  megfile/sftp.py,sha256=uBcLQs-j6Q-q-sWAdd-pgi5Qmb_kq7boJM-0sCfcNO0,26540
16
16
  megfile/sftp_path.py,sha256=CgirHWmNdXdqyIL9ufmlaMpwFhlkQVZhqmfvjUaj7qU,43845
17
17
  megfile/smart.py,sha256=Miz3jyLKmwWBja-8GrSzrumpTarPrFPqXaFQJKwrK1Y,36627
18
18
  megfile/smart_path.py,sha256=Up_6xNZ2019iSzMn_JAU_1H--z-AP6O7SxdXGdeTG0c,7659
19
19
  megfile/stdio.py,sha256=ZwxsnJNJYIT7Iyg5pIw4qiyH8bszG6oAhEJuR-hXGG4,658
20
20
  megfile/stdio_path.py,sha256=cxaDr8rtisTPnN-rjtaEpqQnshwiqwXFUJBM9xWY7Cg,2711
21
- megfile/version.py,sha256=FceFVYf0TTvPdz_-wQYGd2Nu7cQw9bu1MClPA-Hgh0E,25
21
+ megfile/version.py,sha256=e0k-2Nn8dpoGmVJ3Wg03fcRMzM9q9jfKeY7f3OkI7LE,19
22
22
  megfile/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  megfile/lib/base_prefetch_reader.py,sha256=uxVwYknOjc8hLF7q_T2QKMsBqFcrf411ZsuK25CN1eQ,12848
24
24
  megfile/lib/combine_reader.py,sha256=Kp2wEloOUpTlIU7dve87MBpSzmIM-F9OtpTawAjFkiU,4828
@@ -43,10 +43,10 @@ megfile/lib/stdio_handler.py,sha256=IDdgENLQlhigEwkLL4zStueVSzdWg7xVcTF_koof_Ek,
43
43
  megfile/lib/url.py,sha256=ER32pWy9Q2MAk3TraAaNEBWIqUeBmLuM57ol2cs7-Ks,103
44
44
  megfile/utils/__init__.py,sha256=pawmXnCNokWLj338a60b_hK21koYavpEiEohZhsOaGQ,10156
45
45
  megfile/utils/mutex.py,sha256=asb8opGLgK22RiuBJUnfsvB8LnMmodP8KzCVHKmQBWA,2561
46
- megfile-4.1.8.post1.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
47
- megfile-4.1.8.post1.dist-info/licenses/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
48
- megfile-4.1.8.post1.dist-info/METADATA,sha256=7pRHrmLqja2l5oNGGx19IPRYbM-Z0ruvJ-znSi7NOVQ,9601
49
- megfile-4.1.8.post1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- megfile-4.1.8.post1.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
51
- megfile-4.1.8.post1.dist-info/top_level.txt,sha256=i3rMgdU1ZAJekAceojhA-bkm3749PzshtRmLTbeLUPQ,8
52
- megfile-4.1.8.post1.dist-info/RECORD,,
46
+ megfile-4.2.1.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
47
+ megfile-4.2.1.dist-info/licenses/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
48
+ megfile-4.2.1.dist-info/METADATA,sha256=8-Gzye2STZTocHieLky8XR0nAae8sHEmanRVeTWKWYM,9595
49
+ megfile-4.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
+ megfile-4.2.1.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
51
+ megfile-4.2.1.dist-info/top_level.txt,sha256=i3rMgdU1ZAJekAceojhA-bkm3749PzshtRmLTbeLUPQ,8
52
+ megfile-4.2.1.dist-info/RECORD,,