megfile 3.1.5__py3-none-any.whl → 3.1.6.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/cli.py +2 -1
- megfile/config.py +2 -0
- megfile/errors.py +1 -1
- megfile/lib/s3_prefetch_reader.py +5 -1
- megfile/pathlike.py +17 -2
- megfile/s3_path.py +63 -26
- megfile/smart_path.py +27 -20
- megfile/utils/__init__.py +57 -1
- megfile/version.py +1 -1
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/METADATA +1 -1
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/RECORD +16 -16
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/WHEEL +1 -1
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/LICENSE +0 -0
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/LICENSE.pyre +0 -0
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/entry_points.txt +0 -0
- {megfile-3.1.5.dist-info → megfile-3.1.6.post1.dist-info}/top_level.txt +0 -0
megfile/cli.py
CHANGED
|
@@ -29,6 +29,7 @@ from megfile.smart import (
|
|
|
29
29
|
smart_open,
|
|
30
30
|
smart_path_join,
|
|
31
31
|
smart_readlink,
|
|
32
|
+
smart_relpath,
|
|
32
33
|
smart_remove,
|
|
33
34
|
smart_rename,
|
|
34
35
|
smart_scan_stat,
|
|
@@ -78,7 +79,7 @@ def get_echo_path(file_stat, base_path: str = "", full_path: bool = False):
|
|
|
78
79
|
elif full_path:
|
|
79
80
|
path = file_stat.path
|
|
80
81
|
else:
|
|
81
|
-
path =
|
|
82
|
+
path = smart_relpath(file_stat.path, start=base_path)
|
|
82
83
|
return path
|
|
83
84
|
|
|
84
85
|
|
megfile/config.py
CHANGED
megfile/errors.py
CHANGED
|
@@ -366,7 +366,7 @@ def translate_s3_error(s3_error: Exception, s3_url: PathLike) -> Exception:
|
|
|
366
366
|
"Invalid configuration: %r, code: %r, message: %r, endpoint: %r"
|
|
367
367
|
% (s3_url, code, message, s3_endpoint_url(s3_url))
|
|
368
368
|
)
|
|
369
|
-
if code in ("InvalidRange"):
|
|
369
|
+
if code in ("InvalidRange", "Requested Range Not Satisfiable"):
|
|
370
370
|
return S3InvalidRangeError(
|
|
371
371
|
"Index out of range: %r, code: %r, message: %r, endpoint: %r"
|
|
372
372
|
% (
|
|
@@ -76,7 +76,11 @@ class S3PrefetchReader(BasePrefetchReader):
|
|
|
76
76
|
try:
|
|
77
77
|
start, end = 0, self._block_size - 1
|
|
78
78
|
first_index_response = self._fetch_response(start=start, end=end)
|
|
79
|
-
|
|
79
|
+
if "ContentRange" in first_index_response:
|
|
80
|
+
content_size = int(first_index_response["ContentRange"].split("/")[-1])
|
|
81
|
+
else:
|
|
82
|
+
# usually when read a file only have one block
|
|
83
|
+
content_size = int(first_index_response["ContentLength"])
|
|
80
84
|
except S3InvalidRangeError:
|
|
81
85
|
# usually when read a empty file
|
|
82
86
|
# can use minio test empty file: https://hub.docker.com/r/minio/minio
|
megfile/pathlike.py
CHANGED
|
@@ -636,8 +636,8 @@ class URIPath(BaseURIPath):
|
|
|
636
636
|
relative = path[len(other_path) :]
|
|
637
637
|
relative = relative.lstrip("/")
|
|
638
638
|
return type(self)(relative) # pyre-ignore[19]
|
|
639
|
-
|
|
640
|
-
|
|
639
|
+
|
|
640
|
+
raise ValueError("%r does not start with %r" % (path, other))
|
|
641
641
|
|
|
642
642
|
def with_name(self: Self, name: str) -> Self:
|
|
643
643
|
"""Return a new path with the name changed"""
|
|
@@ -655,6 +655,21 @@ class URIPath(BaseURIPath):
|
|
|
655
655
|
raw_suffix = self.suffix
|
|
656
656
|
return self.from_path(path[: len(path) - len(raw_suffix)] + suffix)
|
|
657
657
|
|
|
658
|
+
def relpath(self, start=None):
|
|
659
|
+
"""Return the relative path."""
|
|
660
|
+
if start is None:
|
|
661
|
+
raise TypeError("start is required")
|
|
662
|
+
|
|
663
|
+
other_path = self.from_path(start).path_with_protocol
|
|
664
|
+
path = self.path_with_protocol
|
|
665
|
+
|
|
666
|
+
if path.startswith(other_path):
|
|
667
|
+
relative = path[len(other_path) :]
|
|
668
|
+
relative = relative.lstrip("/")
|
|
669
|
+
return relative
|
|
670
|
+
|
|
671
|
+
raise ValueError("%r does not start with %r" % (path, other_path))
|
|
672
|
+
|
|
658
673
|
def is_absolute(self) -> bool:
|
|
659
674
|
return True
|
|
660
675
|
|
megfile/s3_path.py
CHANGED
|
@@ -7,16 +7,18 @@ from concurrent.futures import ThreadPoolExecutor
|
|
|
7
7
|
from functools import cached_property, lru_cache, wraps
|
|
8
8
|
from logging import getLogger as get_logger
|
|
9
9
|
from typing import IO, Any, BinaryIO, Callable, Dict, Iterator, List, Optional, Tuple
|
|
10
|
+
from urllib.parse import urlparse
|
|
10
11
|
|
|
11
12
|
import boto3
|
|
12
13
|
import botocore
|
|
13
|
-
from botocore.awsrequest import AWSResponse
|
|
14
|
+
from botocore.awsrequest import AWSPreparedRequest, AWSResponse
|
|
14
15
|
|
|
15
16
|
from megfile.config import (
|
|
16
17
|
DEFAULT_BLOCK_SIZE,
|
|
17
18
|
DEFAULT_MAX_BLOCK_SIZE,
|
|
18
19
|
DEFAULT_MIN_BLOCK_SIZE,
|
|
19
20
|
GLOBAL_MAX_WORKERS,
|
|
21
|
+
HTTP_AUTH_HEADERS,
|
|
20
22
|
S3_CLIENT_CACHE_MODE,
|
|
21
23
|
S3_MAX_RETRY_TIMES,
|
|
22
24
|
)
|
|
@@ -76,6 +78,7 @@ from megfile.utils import (
|
|
|
76
78
|
generate_cache_path,
|
|
77
79
|
get_binary_mode,
|
|
78
80
|
get_content_offset,
|
|
81
|
+
is_domain_or_subdomain,
|
|
79
82
|
is_readable,
|
|
80
83
|
necessary_params,
|
|
81
84
|
process_local,
|
|
@@ -122,7 +125,7 @@ max_retries = S3_MAX_RETRY_TIMES
|
|
|
122
125
|
max_keys = 1000
|
|
123
126
|
|
|
124
127
|
|
|
125
|
-
def _patch_make_request(client: botocore.client.BaseClient):
|
|
128
|
+
def _patch_make_request(client: botocore.client.BaseClient, redirect: bool = False):
|
|
126
129
|
def after_callback(result: Tuple[AWSResponse, dict], *args, **kwargs):
|
|
127
130
|
if (
|
|
128
131
|
not isinstance(result, tuple)
|
|
@@ -161,6 +164,32 @@ def _patch_make_request(client: botocore.client.BaseClient):
|
|
|
161
164
|
before_callback=before_callback,
|
|
162
165
|
retry_callback=retry_callback,
|
|
163
166
|
)
|
|
167
|
+
|
|
168
|
+
def patch_send(send):
|
|
169
|
+
def patched_send(request: AWSPreparedRequest) -> AWSResponse:
|
|
170
|
+
response: AWSResponse = send(request)
|
|
171
|
+
if (
|
|
172
|
+
request.method == "GET" # only support GET method for now
|
|
173
|
+
and response.status_code in (301, 302, 307, 308)
|
|
174
|
+
and "Location" in response.headers
|
|
175
|
+
):
|
|
176
|
+
# Permit sending auth/cookie headers from "foo.com" to "sub.foo.com".
|
|
177
|
+
# See also: https://go.dev/src/net/http/client.go#L980
|
|
178
|
+
location = response.headers["Location"]
|
|
179
|
+
ihost = urlparse(request.url).hostname
|
|
180
|
+
dhost = urlparse(location).hostname
|
|
181
|
+
if not is_domain_or_subdomain(dhost, ihost):
|
|
182
|
+
for name in HTTP_AUTH_HEADERS:
|
|
183
|
+
request.headers.pop(name, None)
|
|
184
|
+
request.url = location
|
|
185
|
+
response = send(request)
|
|
186
|
+
return response
|
|
187
|
+
|
|
188
|
+
return patched_send
|
|
189
|
+
|
|
190
|
+
if redirect:
|
|
191
|
+
client._endpoint._send = patch_send(client._endpoint._send)
|
|
192
|
+
|
|
164
193
|
return client
|
|
165
194
|
|
|
166
195
|
|
|
@@ -180,7 +209,11 @@ def parse_s3_url(s3_url: PathLike) -> Tuple[str, str]:
|
|
|
180
209
|
|
|
181
210
|
|
|
182
211
|
def get_scoped_config(profile_name: Optional[str] = None) -> Dict:
|
|
183
|
-
|
|
212
|
+
try:
|
|
213
|
+
session = get_s3_session(profile_name=profile_name)
|
|
214
|
+
except botocore.exceptions.ProfileNotFound:
|
|
215
|
+
session = get_s3_session()
|
|
216
|
+
return session._session.get_scoped_config()
|
|
184
217
|
|
|
185
218
|
|
|
186
219
|
@lru_cache()
|
|
@@ -224,25 +257,22 @@ def get_s3_session(profile_name=None) -> boto3.Session:
|
|
|
224
257
|
)
|
|
225
258
|
|
|
226
259
|
|
|
260
|
+
def get_env_var(env_name: str, profile_name=None):
|
|
261
|
+
if profile_name:
|
|
262
|
+
return os.getenv(f"{profile_name}__{env_name}".upper())
|
|
263
|
+
return os.getenv(env_name.upper())
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def parse_boolean(value: Optional[str], default: bool = False) -> bool:
|
|
267
|
+
if value is None:
|
|
268
|
+
return default
|
|
269
|
+
return value.lower() in ("true", "yes", "1")
|
|
270
|
+
|
|
271
|
+
|
|
227
272
|
def get_access_token(profile_name=None):
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
else "AWS_ACCESS_KEY_ID"
|
|
232
|
-
)
|
|
233
|
-
secret_key_env_name = (
|
|
234
|
-
f"{profile_name}__AWS_SECRET_ACCESS_KEY".upper()
|
|
235
|
-
if profile_name
|
|
236
|
-
else "AWS_SECRET_ACCESS_KEY"
|
|
237
|
-
)
|
|
238
|
-
session_token_env_name = (
|
|
239
|
-
f"{profile_name}__AWS_SESSION_TOKEN".upper()
|
|
240
|
-
if profile_name
|
|
241
|
-
else "AWS_SESSION_TOKEN"
|
|
242
|
-
)
|
|
243
|
-
access_key = os.getenv(access_key_env_name)
|
|
244
|
-
secret_key = os.getenv(secret_key_env_name)
|
|
245
|
-
session_token = os.getenv(session_token_env_name)
|
|
273
|
+
access_key = get_env_var("AWS_ACCESS_KEY_ID", profile_name=profile_name)
|
|
274
|
+
secret_key = get_env_var("AWS_SECRET_ACCESS_KEY", profile_name=profile_name)
|
|
275
|
+
session_token = get_env_var("AWS_SESSION_TOKEN", profile_name=profile_name)
|
|
246
276
|
if access_key and secret_key:
|
|
247
277
|
return access_key, secret_key, session_token
|
|
248
278
|
|
|
@@ -289,10 +319,7 @@ def get_s3_client(
|
|
|
289
319
|
connect_timeout=5, max_pool_connections=GLOBAL_MAX_WORKERS
|
|
290
320
|
)
|
|
291
321
|
|
|
292
|
-
|
|
293
|
-
if profile_name:
|
|
294
|
-
addressing_style_env_key = f"{profile_name}__AWS_S3_ADDRESSING_STYLE".upper()
|
|
295
|
-
addressing_style = os.environ.get(addressing_style_env_key)
|
|
322
|
+
addressing_style = get_env_var("AWS_S3_ADDRESSING_STYLE", profile_name=profile_name)
|
|
296
323
|
if addressing_style:
|
|
297
324
|
config = config.merge(
|
|
298
325
|
botocore.config.Config(s3={"addressing_style": addressing_style})
|
|
@@ -303,15 +330,25 @@ def get_s3_client(
|
|
|
303
330
|
session = get_s3_session(profile_name=profile_name)
|
|
304
331
|
except botocore.exceptions.ProfileNotFound:
|
|
305
332
|
session = get_s3_session()
|
|
333
|
+
|
|
334
|
+
s3_config = get_scoped_config(profile_name=profile_name).get("s3", {})
|
|
335
|
+
verify = get_env_var("AWS_S3_VERIFY", profile_name=profile_name)
|
|
336
|
+
verify = verify or s3_config.get("verify")
|
|
337
|
+
verify = parse_boolean(verify, default=True)
|
|
338
|
+
redirect = get_env_var("AWS_S3_REDIRECT", profile_name=profile_name)
|
|
339
|
+
redirect = redirect or s3_config.get("redirect")
|
|
340
|
+
redirect = parse_boolean(redirect, default=False)
|
|
341
|
+
|
|
306
342
|
client = session.client(
|
|
307
343
|
"s3",
|
|
308
344
|
endpoint_url=get_endpoint_url(profile_name=profile_name),
|
|
345
|
+
verify=verify,
|
|
309
346
|
config=config,
|
|
310
347
|
aws_access_key_id=access_key,
|
|
311
348
|
aws_secret_access_key=secret_key,
|
|
312
349
|
aws_session_token=session_token,
|
|
313
350
|
)
|
|
314
|
-
client = _patch_make_request(client)
|
|
351
|
+
client = _patch_make_request(client, redirect=redirect)
|
|
315
352
|
return client
|
|
316
353
|
|
|
317
354
|
|
megfile/smart_path.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from configparser import ConfigParser
|
|
3
3
|
from pathlib import PurePath
|
|
4
|
-
from typing import Dict, Tuple, Union
|
|
4
|
+
from typing import Dict, Optional, Tuple, Union
|
|
5
5
|
|
|
6
6
|
from megfile.lib.compat import fspath
|
|
7
7
|
from megfile.lib.url import get_url_scheme
|
|
8
|
-
from megfile.utils import
|
|
8
|
+
from megfile.utils import cached_classproperty
|
|
9
9
|
|
|
10
10
|
from .errors import ProtocolExistsError, ProtocolNotFoundError
|
|
11
11
|
from .interfaces import BasePath, BaseURIPath, PathLike
|
|
@@ -54,15 +54,15 @@ class SmartPath(BasePath):
|
|
|
54
54
|
self.path = str(pathlike)
|
|
55
55
|
self.pathlike = pathlike
|
|
56
56
|
|
|
57
|
-
@
|
|
57
|
+
@cached_classproperty
|
|
58
58
|
def _aliases(cls) -> Dict[str, Dict[str, str]]:
|
|
59
59
|
config_path = os.path.expanduser(aliases_config)
|
|
60
|
-
|
|
61
|
-
setattr(cls, "_aliases", aliases)
|
|
62
|
-
return aliases
|
|
60
|
+
return _load_aliases_config(config_path)
|
|
63
61
|
|
|
64
|
-
@
|
|
65
|
-
def _extract_protocol(
|
|
62
|
+
@classmethod
|
|
63
|
+
def _extract_protocol(
|
|
64
|
+
cls, path: Union[PathLike, int]
|
|
65
|
+
) -> Tuple[str, Union[str, int]]:
|
|
66
66
|
if isinstance(path, int):
|
|
67
67
|
protocol = "file"
|
|
68
68
|
path_without_protocol = path
|
|
@@ -74,27 +74,26 @@ class SmartPath(BasePath):
|
|
|
74
74
|
else:
|
|
75
75
|
path_without_protocol = path[len(protocol) + 3 :]
|
|
76
76
|
elif isinstance(path, (BaseURIPath, SmartPath)):
|
|
77
|
-
|
|
78
|
-
path_without_protocol = str(path)
|
|
77
|
+
return str(path.protocol), str(path)
|
|
79
78
|
elif isinstance(path, (PurePath, BasePath)):
|
|
80
|
-
|
|
79
|
+
return SmartPath._extract_protocol(fspath(path))
|
|
81
80
|
else:
|
|
82
81
|
raise ProtocolNotFoundError("protocol not found: %r" % path)
|
|
83
|
-
return protocol, path_without_protocol
|
|
84
|
-
|
|
85
|
-
@classmethod
|
|
86
|
-
def _create_pathlike(cls, path: Union[PathLike, int]) -> BaseURIPath:
|
|
87
|
-
protocol, path_without_protocol = cls._extract_protocol(path)
|
|
88
82
|
aliases: Dict[str, Dict[str, str]] = cls._aliases # pyre-ignore[9]
|
|
89
83
|
if protocol in aliases:
|
|
90
84
|
protocol = aliases[protocol]["protocol"]
|
|
91
|
-
path =
|
|
85
|
+
path = "%s://%s" % (protocol, path_without_protocol)
|
|
86
|
+
return protocol, path
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def _create_pathlike(cls, path: Union[PathLike, int]) -> BaseURIPath:
|
|
90
|
+
protocol, unaliased_path = cls._extract_protocol(path)
|
|
92
91
|
if protocol.startswith("s3+"):
|
|
93
92
|
protocol = "s3"
|
|
94
93
|
if protocol not in cls._registered_protocols:
|
|
95
94
|
raise ProtocolNotFoundError("protocol %r not found: %r" % (protocol, path))
|
|
96
95
|
path_class = cls._registered_protocols[protocol]
|
|
97
|
-
return path_class(
|
|
96
|
+
return path_class(unaliased_path)
|
|
98
97
|
|
|
99
98
|
@classmethod
|
|
100
99
|
def register(cls, path_class, override_ok: bool = False):
|
|
@@ -137,7 +136,6 @@ class SmartPath(BasePath):
|
|
|
137
136
|
joinpath = _bind_function("joinpath")
|
|
138
137
|
abspath = _bind_function("abspath")
|
|
139
138
|
realpath = _bind_function("realpath")
|
|
140
|
-
relpath = _bind_function("relpath")
|
|
141
139
|
is_absolute = _bind_function("is_absolute")
|
|
142
140
|
is_mount = _bind_function("is_mount")
|
|
143
141
|
md5 = _bind_function("md5")
|
|
@@ -150,6 +148,16 @@ class SmartPath(BasePath):
|
|
|
150
148
|
def from_uri(cls, path: str):
|
|
151
149
|
return cls(path)
|
|
152
150
|
|
|
151
|
+
def relpath(self, start: Optional[str] = None) -> str:
|
|
152
|
+
"""Return the relative path of given path
|
|
153
|
+
|
|
154
|
+
:param start: Given start directory
|
|
155
|
+
:returns: Relative path from start
|
|
156
|
+
"""
|
|
157
|
+
if start is not None:
|
|
158
|
+
_, start = SmartPath._extract_protocol(fspath(start))
|
|
159
|
+
return self.pathlike.relpath(start=start)
|
|
160
|
+
|
|
153
161
|
as_uri = _bind_function("as_uri")
|
|
154
162
|
as_posix = _bind_function("as_posix")
|
|
155
163
|
__lt__ = _bind_function("__lt__")
|
|
@@ -170,7 +178,6 @@ class SmartPath(BasePath):
|
|
|
170
178
|
is_mount = _bind_function("is_mount")
|
|
171
179
|
abspath = _bind_function("abspath")
|
|
172
180
|
realpath = _bind_function("realpath")
|
|
173
|
-
relpath = _bind_function("relpath")
|
|
174
181
|
iterdir = _bind_function("iterdir")
|
|
175
182
|
cwd = _bind_function("cwd")
|
|
176
183
|
home = _bind_function("home")
|
megfile/utils/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@ import math
|
|
|
4
4
|
import os
|
|
5
5
|
import uuid
|
|
6
6
|
from copy import copy
|
|
7
|
-
from functools import wraps
|
|
7
|
+
from functools import cached_property, wraps
|
|
8
8
|
from io import (
|
|
9
9
|
BufferedIOBase,
|
|
10
10
|
BufferedRandom,
|
|
@@ -15,6 +15,7 @@ from io import (
|
|
|
15
15
|
TextIOBase,
|
|
16
16
|
TextIOWrapper,
|
|
17
17
|
)
|
|
18
|
+
from threading import RLock
|
|
18
19
|
from typing import IO, Callable, Optional
|
|
19
20
|
|
|
20
21
|
from megfile.utils.mutex import ProcessLocal, ThreadLocal
|
|
@@ -298,3 +299,58 @@ class classproperty(property):
|
|
|
298
299
|
"""
|
|
299
300
|
# call this method only on the class, not the instance
|
|
300
301
|
super(classproperty, self).__delete__(_get_class(cls_or_obj))
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class cached_classproperty(cached_property):
|
|
305
|
+
"""
|
|
306
|
+
The use this class as a decorator for your class property with cache.
|
|
307
|
+
Example:
|
|
308
|
+
@cached_classproperty
|
|
309
|
+
def prop(cls):
|
|
310
|
+
return "value"
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
def __init__(self, func: Callable) -> None:
|
|
314
|
+
"""
|
|
315
|
+
This method initializes the cached_classproperty instance.
|
|
316
|
+
@param func: The function to be called when the property value is requested.
|
|
317
|
+
"""
|
|
318
|
+
super().__init__(func)
|
|
319
|
+
# Python 3.12 removed the lock attribute from cached_property.
|
|
320
|
+
# Maybe we should remove this in the future.
|
|
321
|
+
# See also: https://github.com/python/cpython/pull/101890
|
|
322
|
+
# https://github.com/python/cpython/issues/87634
|
|
323
|
+
if not hasattr(func, "lock"):
|
|
324
|
+
self.lock = RLock()
|
|
325
|
+
|
|
326
|
+
def __get__( # pyre-ignore[14]
|
|
327
|
+
self,
|
|
328
|
+
_,
|
|
329
|
+
cls, # pytype: disable=signature-mismatch
|
|
330
|
+
) -> object:
|
|
331
|
+
"""
|
|
332
|
+
This method gets called when a property value is requested.
|
|
333
|
+
@param cls: The class type of the above instance.
|
|
334
|
+
@return: The value of the property.
|
|
335
|
+
"""
|
|
336
|
+
if self.attrname is None:
|
|
337
|
+
raise TypeError(
|
|
338
|
+
"Cannot use cached_classproperty instance without calling "
|
|
339
|
+
"__set_name__ on it."
|
|
340
|
+
)
|
|
341
|
+
with self.lock:
|
|
342
|
+
# check if another thread filled cache while we awaited lock
|
|
343
|
+
# cannot use getattr since it will cause RecursionError
|
|
344
|
+
val = cls.__dict__[self.attrname]
|
|
345
|
+
if val is self:
|
|
346
|
+
val = self.func(cls)
|
|
347
|
+
setattr(cls, self.attrname, val)
|
|
348
|
+
return val
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def is_domain_or_subdomain(sub, parent):
|
|
352
|
+
if sub == parent:
|
|
353
|
+
return True
|
|
354
|
+
if sub.endswith(f".{parent}"):
|
|
355
|
+
return True
|
|
356
|
+
return False
|
megfile/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = "3.1.
|
|
1
|
+
VERSION = "3.1.6.post1"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
docs/conf.py,sha256=sfDSly5jO8W_RmuAptOIp4hd8dNcO-9a5XrHTbxFnNo,2448
|
|
2
2
|
megfile/__init__.py,sha256=i2Lbq_VxIgppaqwkxG0_H35dRfcjJ4mCYWjprOf4hHo,7318
|
|
3
|
-
megfile/cli.py,sha256=
|
|
4
|
-
megfile/config.py,sha256=
|
|
5
|
-
megfile/errors.py,sha256=
|
|
3
|
+
megfile/cli.py,sha256=0Sgbz3jeUryVll9Aa6R0MpJdQJUGENvz55YF7Jm1Uxc,23482
|
|
4
|
+
megfile/config.py,sha256=k52eO9YUyYRJ0-bsscAXcfEt8xIAHGOHdLSnEJf6z7k,2411
|
|
5
|
+
megfile/errors.py,sha256=a55qKQgyfiLmV-qnojUFzq2gu9JXpj3ZiC2qVaWyUTA,14160
|
|
6
6
|
megfile/fs.py,sha256=dgj5fW-EEzQNdjMF2tkB5DjXu3iHQbtLi5PSIMxR8fc,11966
|
|
7
7
|
megfile/fs_path.py,sha256=Ffvukc176beH5aQMZXXtwH6ApwLYXPViCIUP0pijgT0,41590
|
|
8
8
|
megfile/hdfs.py,sha256=latguOuuzAmg-yWOy3Sm723CJ0ybN_eSHRubVNqhcMU,9202
|
|
@@ -10,16 +10,16 @@ megfile/hdfs_path.py,sha256=0XLtABufwqL-y8igOxzOJz6zOGppuBp2f2SwXIMvvYg,27299
|
|
|
10
10
|
megfile/http.py,sha256=2Z2yqyhU-zcJCJwSNyBsxsZ7f2FT9X6fcednsbHDsFM,2025
|
|
11
11
|
megfile/http_path.py,sha256=BhMNjQVB85IaCGGIKzgEfY73mAVdCzJP08W1RuGeMRA,16119
|
|
12
12
|
megfile/interfaces.py,sha256=7C53Q2FAVFmOEnplfplvWqHab29HJE5RQnpfdb4loVY,8679
|
|
13
|
-
megfile/pathlike.py,sha256=
|
|
13
|
+
megfile/pathlike.py,sha256=5VAKIArm2UqrpMBJMoNAEydFxLd1mjCZ8iQnKFUIYu0,31274
|
|
14
14
|
megfile/s3.py,sha256=7SdfLjAePVh-bpRyuj566VB4Qa7KP86rCJGzYANR7wQ,13008
|
|
15
|
-
megfile/s3_path.py,sha256=
|
|
15
|
+
megfile/s3_path.py,sha256=kOrP45zQbxCxNQcoovd060QARkP8QWYKd8BQGfxGY2g,95447
|
|
16
16
|
megfile/sftp.py,sha256=vyDnYXX3i1j2fhXMC8YCeX-66MDb9wrBQQjQVhZx0uo,13004
|
|
17
17
|
megfile/sftp_path.py,sha256=4tByWvUJK1KBJoa3t5aoWYnZpaRWN9nQIE6ZyiGHrbk,53519
|
|
18
18
|
megfile/smart.py,sha256=Vr4R7HpjXjt587KOc2-1QGbQ5EsZ48YRzCaK0rz3IS0,36108
|
|
19
|
-
megfile/smart_path.py,sha256=
|
|
19
|
+
megfile/smart_path.py,sha256=Wsn6fR9g7NTwNwwvZ_0H39NLHIlOLnCqK-ZY0n5CvKk,7812
|
|
20
20
|
megfile/stdio.py,sha256=UYe-h440Wc4f5COOzOTG1svnp5nFzrfpixehJ0_0_NY,653
|
|
21
21
|
megfile/stdio_path.py,sha256=7jzVdreamO18yBWZM7Pp71cO7GmrYb0M0qyQde2Ypq4,2706
|
|
22
|
-
megfile/version.py,sha256=
|
|
22
|
+
megfile/version.py,sha256=XtGruYz10E7g9ijesLiQ9efrLMwPQjA29gsjMfo552o,25
|
|
23
23
|
megfile/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
megfile/lib/base_prefetch_reader.py,sha256=CaYWuiKmlk4Utr0IFDPwPC58wV2jBAhqpxhwhRHc734,13652
|
|
25
25
|
megfile/lib/combine_reader.py,sha256=uSzo3PmhD5ck6_Vv6dFU5vVx4boeA97VS-puPyhF_BE,4657
|
|
@@ -37,19 +37,19 @@ megfile/lib/s3_cached_handler.py,sha256=QrQKck06ye16o7GD71T-fVCseKlOhsxp82LtBTtA
|
|
|
37
37
|
megfile/lib/s3_limited_seekable_writer.py,sha256=v-e7rfFBfWCSQVtJIaFHM_i0Hb1FkfVLHlhawo5MOIk,6358
|
|
38
38
|
megfile/lib/s3_memory_handler.py,sha256=NGKWbI4LG2cmV06CP7KOVPqS_BNpm3ApqKi5ibgIBvQ,4208
|
|
39
39
|
megfile/lib/s3_pipe_handler.py,sha256=DY1UTNCq8oD3QWXNb4orOiz3EoEAo6dhwmZZdk6h1bU,3694
|
|
40
|
-
megfile/lib/s3_prefetch_reader.py,sha256=
|
|
40
|
+
megfile/lib/s3_prefetch_reader.py,sha256=gjnnYI95LFwxpneDFfLBzw8gvT1Vc8yJJlBL101oysI,4501
|
|
41
41
|
megfile/lib/s3_share_cache_reader.py,sha256=jhGL1B6NPv68cQnW1Jf7ey-zTQ8XfiJg5ILDNgRWHy0,3671
|
|
42
42
|
megfile/lib/shadow_handler.py,sha256=TntewlvIW9ZxCfmqASDQREHoiZ8v42faOe9sovQYQz0,2779
|
|
43
43
|
megfile/lib/stdio_handler.py,sha256=IDdgENLQlhigEwkLL4zStueVSzdWg7xVcTF_koof_Ek,1987
|
|
44
44
|
megfile/lib/url.py,sha256=ER32pWy9Q2MAk3TraAaNEBWIqUeBmLuM57ol2cs7-Ks,103
|
|
45
|
-
megfile/utils/__init__.py,sha256=
|
|
45
|
+
megfile/utils/__init__.py,sha256=RAj8dAJZX5TkWKJu3Ip78uhA5XZ8wpir61eCm6bAnd4,10874
|
|
46
46
|
megfile/utils/mutex.py,sha256=asb8opGLgK22RiuBJUnfsvB8LnMmodP8KzCVHKmQBWA,2561
|
|
47
47
|
scripts/convert_results_to_sarif.py,sha256=nDiOfsedb22Ps7ZodmYdlXZlxv54fRxCQgOZsB2OkNk,2833
|
|
48
48
|
scripts/generate_file.py,sha256=-mTcBiqiQ1juvqojVfVZ-uZWgpANHJNdhrF7s68zNfc,10903
|
|
49
|
-
megfile-3.1.
|
|
50
|
-
megfile-3.1.
|
|
51
|
-
megfile-3.1.
|
|
52
|
-
megfile-3.1.
|
|
53
|
-
megfile-3.1.
|
|
54
|
-
megfile-3.1.
|
|
55
|
-
megfile-3.1.
|
|
49
|
+
megfile-3.1.6.post1.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
50
|
+
megfile-3.1.6.post1.dist-info/LICENSE.pyre,sha256=9lf5nT-5ZH25JijpYAequ0bl8E8z5JmZB1qrjiUMp84,1080
|
|
51
|
+
megfile-3.1.6.post1.dist-info/METADATA,sha256=AEZWwtG0zg1mZzAIyM9YHZ5JmbS0Bwc6YCMsGFrTYDo,9184
|
|
52
|
+
megfile-3.1.6.post1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
53
|
+
megfile-3.1.6.post1.dist-info/entry_points.txt,sha256=M6ZWSSv5_5_QtIpZafy3vq7WuOJ_5dSGQQnEZbByt2Q,49
|
|
54
|
+
megfile-3.1.6.post1.dist-info/top_level.txt,sha256=oTnYXo1Z3V61qSWAKtnY9RkDgRSHvfRN38FQae6E0W0,50
|
|
55
|
+
megfile-3.1.6.post1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|