fsspec 2025.3.0__py3-none-any.whl → 2025.3.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.
- fsspec/_version.py +2 -2
- fsspec/asyn.py +12 -0
- fsspec/caching.py +40 -1
- fsspec/implementations/cached.py +13 -1
- fsspec/implementations/github.py +46 -18
- fsspec/implementations/http_sync.py +6 -7
- fsspec/registry.py +2 -2
- {fsspec-2025.3.0.dist-info → fsspec-2025.3.1.dist-info}/METADATA +1 -1
- {fsspec-2025.3.0.dist-info → fsspec-2025.3.1.dist-info}/RECORD +11 -11
- {fsspec-2025.3.0.dist-info → fsspec-2025.3.1.dist-info}/WHEEL +0 -0
- {fsspec-2025.3.0.dist-info → fsspec-2025.3.1.dist-info}/licenses/LICENSE +0 -0
fsspec/_version.py
CHANGED
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '2025.3.
|
|
21
|
-
__version_tuple__ = version_tuple = (2025, 3,
|
|
20
|
+
__version__ = version = '2025.3.1'
|
|
21
|
+
__version_tuple__ = version_tuple = (2025, 3, 1)
|
fsspec/asyn.py
CHANGED
|
@@ -151,6 +151,18 @@ def get_loop():
|
|
|
151
151
|
return loop[0]
|
|
152
152
|
|
|
153
153
|
|
|
154
|
+
def reset_after_fork():
|
|
155
|
+
global lock
|
|
156
|
+
loop[0] = None
|
|
157
|
+
iothread[0] = None
|
|
158
|
+
lock = None
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if hasattr(os, "register_at_fork"):
|
|
162
|
+
# should be posix; this will do nothing for spawn or forkserver subprocesses
|
|
163
|
+
os.register_at_fork(after_in_child=reset_after_fork)
|
|
164
|
+
|
|
165
|
+
|
|
154
166
|
if TYPE_CHECKING:
|
|
155
167
|
import resource
|
|
156
168
|
|
fsspec/caching.py
CHANGED
|
@@ -37,6 +37,7 @@ T = TypeVar("T")
|
|
|
37
37
|
logger = logging.getLogger("fsspec")
|
|
38
38
|
|
|
39
39
|
Fetcher = Callable[[int, int], bytes] # Maps (start, end) to bytes
|
|
40
|
+
MultiFetcher = Callable[list[[int, int]], bytes] # Maps [(start, end)] to bytes
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
class BaseCache:
|
|
@@ -109,6 +110,26 @@ class MMapCache(BaseCache):
|
|
|
109
110
|
Ensure there is enough disc space in the temporary location.
|
|
110
111
|
|
|
111
112
|
This cache method might only work on posix
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
blocksize: int
|
|
117
|
+
How far to read ahead in numbers of bytes
|
|
118
|
+
fetcher: Fetcher
|
|
119
|
+
Function of the form f(start, end) which gets bytes from remote as
|
|
120
|
+
specified
|
|
121
|
+
size: int
|
|
122
|
+
How big this file is
|
|
123
|
+
location: str
|
|
124
|
+
Where to create the temporary file. If None, a temporary file is
|
|
125
|
+
created using tempfile.TemporaryFile().
|
|
126
|
+
blocks: set[int]
|
|
127
|
+
Set of block numbers that have already been fetched. If None, an empty
|
|
128
|
+
set is created.
|
|
129
|
+
multi_fetcher: MultiFetcher
|
|
130
|
+
Function of the form f([(start, end)]) which gets bytes from remote
|
|
131
|
+
as specified. This function is used to fetch multiple blocks at once.
|
|
132
|
+
If not specified, the fetcher function is used instead.
|
|
112
133
|
"""
|
|
113
134
|
|
|
114
135
|
name = "mmap"
|
|
@@ -120,10 +141,12 @@ class MMapCache(BaseCache):
|
|
|
120
141
|
size: int,
|
|
121
142
|
location: str | None = None,
|
|
122
143
|
blocks: set[int] | None = None,
|
|
144
|
+
multi_fetcher: MultiFetcher | None = None,
|
|
123
145
|
) -> None:
|
|
124
146
|
super().__init__(blocksize, fetcher, size)
|
|
125
147
|
self.blocks = set() if blocks is None else blocks
|
|
126
148
|
self.location = location
|
|
149
|
+
self.multi_fetcher = multi_fetcher
|
|
127
150
|
self.cache = self._makefile()
|
|
128
151
|
|
|
129
152
|
def _makefile(self) -> mmap.mmap | bytearray:
|
|
@@ -164,6 +187,8 @@ class MMapCache(BaseCache):
|
|
|
164
187
|
# Count the number of blocks already cached
|
|
165
188
|
self.hit_count += sum(1 for i in block_range if i in self.blocks)
|
|
166
189
|
|
|
190
|
+
ranges = []
|
|
191
|
+
|
|
167
192
|
# Consolidate needed blocks.
|
|
168
193
|
# Algorithm adapted from Python 2.x itertools documentation.
|
|
169
194
|
# We are grouping an enumerated sequence of blocks. By comparing when the difference
|
|
@@ -185,13 +210,27 @@ class MMapCache(BaseCache):
|
|
|
185
210
|
logger.debug(
|
|
186
211
|
f"MMap get blocks {_blocks[0]}-{_blocks[-1]} ({sstart}-{send})"
|
|
187
212
|
)
|
|
188
|
-
|
|
213
|
+
ranges.append((sstart, send))
|
|
189
214
|
|
|
190
215
|
# Update set of cached blocks
|
|
191
216
|
self.blocks.update(_blocks)
|
|
192
217
|
# Update cache statistics with number of blocks we had to cache
|
|
193
218
|
self.miss_count += len(_blocks)
|
|
194
219
|
|
|
220
|
+
if not ranges:
|
|
221
|
+
return self.cache[start:end]
|
|
222
|
+
|
|
223
|
+
if self.multi_fetcher:
|
|
224
|
+
logger.debug(f"MMap get blocks {ranges}")
|
|
225
|
+
for idx, r in enumerate(self.multi_fetcher(ranges)):
|
|
226
|
+
(sstart, send) = ranges[idx]
|
|
227
|
+
logger.debug(f"MMap copy block ({sstart}-{send}")
|
|
228
|
+
self.cache[sstart:send] = r
|
|
229
|
+
else:
|
|
230
|
+
for sstart, send in ranges:
|
|
231
|
+
logger.debug(f"MMap get block ({sstart}-{send}")
|
|
232
|
+
self.cache[sstart:send] = self.fetcher(sstart, send)
|
|
233
|
+
|
|
195
234
|
return self.cache[start:end]
|
|
196
235
|
|
|
197
236
|
def __getstate__(self) -> dict[str, Any]:
|
fsspec/implementations/cached.py
CHANGED
|
@@ -362,7 +362,19 @@ class CachingFileSystem(AbstractFileSystem):
|
|
|
362
362
|
)
|
|
363
363
|
else:
|
|
364
364
|
detail["blocksize"] = f.blocksize
|
|
365
|
-
|
|
365
|
+
|
|
366
|
+
def _fetch_ranges(ranges):
|
|
367
|
+
return self.fs.cat_ranges(
|
|
368
|
+
[path] * len(ranges),
|
|
369
|
+
[r[0] for r in ranges],
|
|
370
|
+
[r[1] for r in ranges],
|
|
371
|
+
**kwargs,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
multi_fetcher = None if self.compression else _fetch_ranges
|
|
375
|
+
f.cache = MMapCache(
|
|
376
|
+
f.blocksize, f._fetch_range, f.size, fn, blocks, multi_fetcher=multi_fetcher
|
|
377
|
+
)
|
|
366
378
|
close = f.close
|
|
367
379
|
f.close = lambda: self.close_and_update(f, close)
|
|
368
380
|
self.save_cache()
|
fsspec/implementations/github.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import base64
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import requests
|
|
4
4
|
|
|
5
5
|
from ..spec import AbstractFileSystem
|
|
6
6
|
from ..utils import infer_storage_options
|
|
@@ -16,8 +16,10 @@ class GithubFileSystem(AbstractFileSystem):
|
|
|
16
16
|
repository. You may specify a point in the repos history, by SHA, branch
|
|
17
17
|
or tag (default is current master).
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
For files less than 1 MB in size, file content is returned directly in a
|
|
20
|
+
MemoryFile. For larger files, or for files tracked by git-lfs, file content
|
|
21
|
+
is returned as an HTTPFile wrapping the ``download_url`` provided by the
|
|
22
|
+
GitHub API.
|
|
21
23
|
|
|
22
24
|
When using fsspec.open, allows URIs of the form:
|
|
23
25
|
|
|
@@ -36,7 +38,7 @@ class GithubFileSystem(AbstractFileSystem):
|
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
url = "https://api.github.com/repos/{org}/{repo}/git/trees/{sha}"
|
|
39
|
-
|
|
41
|
+
content_url = "https://api.github.com/repos/{org}/{repo}/contents/{path}?ref={sha}"
|
|
40
42
|
protocol = "github"
|
|
41
43
|
timeout = (60, 60) # connect, read timeouts
|
|
42
44
|
|
|
@@ -63,6 +65,12 @@ class GithubFileSystem(AbstractFileSystem):
|
|
|
63
65
|
|
|
64
66
|
self.root = sha
|
|
65
67
|
self.ls("")
|
|
68
|
+
try:
|
|
69
|
+
from .http import HTTPFileSystem
|
|
70
|
+
|
|
71
|
+
self.http_fs = HTTPFileSystem(**kwargs)
|
|
72
|
+
except ImportError:
|
|
73
|
+
self.http_fs = None
|
|
66
74
|
|
|
67
75
|
@property
|
|
68
76
|
def kw(self):
|
|
@@ -212,28 +220,48 @@ class GithubFileSystem(AbstractFileSystem):
|
|
|
212
220
|
path,
|
|
213
221
|
mode="rb",
|
|
214
222
|
block_size=None,
|
|
215
|
-
autocommit=True,
|
|
216
223
|
cache_options=None,
|
|
217
224
|
sha=None,
|
|
218
225
|
**kwargs,
|
|
219
226
|
):
|
|
220
227
|
if mode != "rb":
|
|
221
228
|
raise NotImplementedError
|
|
222
|
-
|
|
229
|
+
|
|
230
|
+
# construct a url to hit the GitHub API's repo contents API
|
|
231
|
+
url = self.content_url.format(
|
|
223
232
|
org=self.org, repo=self.repo, path=path, sha=sha or self.root
|
|
224
233
|
)
|
|
234
|
+
|
|
235
|
+
# make a request to this API, and parse the response as JSON
|
|
225
236
|
r = requests.get(url, timeout=self.timeout, **self.kw)
|
|
226
237
|
if r.status_code == 404:
|
|
227
238
|
raise FileNotFoundError(path)
|
|
228
239
|
r.raise_for_status()
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
content_json = r.json()
|
|
241
|
+
|
|
242
|
+
# if the response's content key is not empty, try to parse it as base64
|
|
243
|
+
if content_json["content"]:
|
|
244
|
+
content = base64.b64decode(content_json["content"])
|
|
245
|
+
|
|
246
|
+
# as long as the content does not start with the string
|
|
247
|
+
# "version https://git-lfs.github.com/"
|
|
248
|
+
# then it is probably not a git-lfs pointer and we can just return
|
|
249
|
+
# the content directly
|
|
250
|
+
if not content.startswith(b"version https://git-lfs.github.com/"):
|
|
251
|
+
return MemoryFile(None, None, content)
|
|
252
|
+
|
|
253
|
+
# we land here if the content was not present in the first response
|
|
254
|
+
# (regular file over 1MB or git-lfs tracked file)
|
|
255
|
+
# in this case, we get let the HTTPFileSystem handle the download
|
|
256
|
+
if self.http_fs is None:
|
|
257
|
+
raise ImportError(
|
|
258
|
+
"Please install fsspec[http] to access github files >1 MB "
|
|
259
|
+
"or git-lfs tracked files."
|
|
260
|
+
)
|
|
261
|
+
return self.http_fs.open(
|
|
262
|
+
content_json["download_url"],
|
|
263
|
+
mode=mode,
|
|
264
|
+
block_size=block_size,
|
|
265
|
+
cache_options=cache_options,
|
|
266
|
+
**kwargs,
|
|
267
|
+
)
|
|
@@ -110,7 +110,6 @@ class ResponseProxy:
|
|
|
110
110
|
self.stream = False
|
|
111
111
|
return self.raw
|
|
112
112
|
|
|
113
|
-
@property
|
|
114
113
|
def json(self):
|
|
115
114
|
return loads(self.text)
|
|
116
115
|
|
|
@@ -201,7 +200,7 @@ class HTTPFileSystem(AbstractFileSystem):
|
|
|
201
200
|
you are testing pyodide/pyscript integration***
|
|
202
201
|
"""
|
|
203
202
|
|
|
204
|
-
protocol = ("http", "https", "
|
|
203
|
+
protocol = ("http", "https", "sync-http", "sync-https")
|
|
205
204
|
sep = "/"
|
|
206
205
|
|
|
207
206
|
def __init__(
|
|
@@ -269,7 +268,7 @@ class HTTPFileSystem(AbstractFileSystem):
|
|
|
269
268
|
|
|
270
269
|
@property
|
|
271
270
|
def fsid(self):
|
|
272
|
-
return "
|
|
271
|
+
return "sync-http"
|
|
273
272
|
|
|
274
273
|
def encode_url(self, url):
|
|
275
274
|
if yarl:
|
|
@@ -279,8 +278,8 @@ class HTTPFileSystem(AbstractFileSystem):
|
|
|
279
278
|
@classmethod
|
|
280
279
|
def _strip_protocol(cls, path: str) -> str:
|
|
281
280
|
"""For HTTP, we always want to keep the full URL"""
|
|
282
|
-
path = path.replace("
|
|
283
|
-
"
|
|
281
|
+
path = path.replace("sync-http://", "http://").replace(
|
|
282
|
+
"sync-https://", "https://"
|
|
284
283
|
)
|
|
285
284
|
return path
|
|
286
285
|
|
|
@@ -918,8 +917,8 @@ def _file_info(url, session, size_policy="head", **kwargs):
|
|
|
918
917
|
def register():
|
|
919
918
|
register_implementation("http", HTTPFileSystem, clobber=True)
|
|
920
919
|
register_implementation("https", HTTPFileSystem, clobber=True)
|
|
921
|
-
register_implementation("
|
|
922
|
-
register_implementation("
|
|
920
|
+
register_implementation("sync-http", HTTPFileSystem, clobber=True)
|
|
921
|
+
register_implementation("sync-https", HTTPFileSystem, clobber=True)
|
|
923
922
|
|
|
924
923
|
|
|
925
924
|
register()
|
fsspec/registry.py
CHANGED
|
@@ -73,7 +73,7 @@ known_implementations = {
|
|
|
73
73
|
"err": "pyarrow and local java libraries required for HDFS",
|
|
74
74
|
},
|
|
75
75
|
"async_wrapper": {
|
|
76
|
-
"class": "
|
|
76
|
+
"class": "fsspec.asyn_wrapper.AsyncWrapperFileSystem",
|
|
77
77
|
},
|
|
78
78
|
"asynclocal": {
|
|
79
79
|
"class": "morefs.asyn_local.AsyncLocalFileSystem",
|
|
@@ -248,7 +248,7 @@ def get_filesystem_class(protocol):
|
|
|
248
248
|
try:
|
|
249
249
|
register_implementation(protocol, _import_class(bit["class"]))
|
|
250
250
|
except ImportError as e:
|
|
251
|
-
raise ImportError(bit
|
|
251
|
+
raise ImportError(bit.get("err")) from e
|
|
252
252
|
cls = registry[protocol]
|
|
253
253
|
if getattr(cls, "protocol", None) in ("abstract", None):
|
|
254
254
|
cls.protocol = protocol
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fsspec
|
|
3
|
-
Version: 2025.3.
|
|
3
|
+
Version: 2025.3.1
|
|
4
4
|
Summary: File-system specification
|
|
5
5
|
Project-URL: Changelog, https://filesystem-spec.readthedocs.io/en/latest/changelog.html
|
|
6
6
|
Project-URL: Documentation, https://filesystem-spec.readthedocs.io/en/latest/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
fsspec/__init__.py,sha256=l9MJaNNV2d4wKpCtMvXDr55n92DkdrAayGy3F9ICjzk,1998
|
|
2
|
-
fsspec/_version.py,sha256=
|
|
2
|
+
fsspec/_version.py,sha256=UTo0k75fb91X4ciJgm5Nvk4otinCDkfq8764_G1IYzQ,517
|
|
3
3
|
fsspec/archive.py,sha256=vM6t_lgV6lBWbBYwpm3S4ofBQFQxUPr5KkDQrrQcQro,2411
|
|
4
|
-
fsspec/asyn.py,sha256=
|
|
5
|
-
fsspec/caching.py,sha256=
|
|
4
|
+
fsspec/asyn.py,sha256=VJ2jBdYgUjV4_dETpKeCp2wF1XHAdeUET95d2HqNZck,36776
|
|
5
|
+
fsspec/caching.py,sha256=pGEBXy2hUh7YBZdZAcCT-38LFmJFDWU9gbmQi05AvFY,34292
|
|
6
6
|
fsspec/callbacks.py,sha256=BDIwLzK6rr_0V5ch557fSzsivCElpdqhXr5dZ9Te-EE,9210
|
|
7
7
|
fsspec/compression.py,sha256=jCSUMJu-zSNyrusnHT0wKXgOd1tTJR6vM126i5SR5Zc,4865
|
|
8
8
|
fsspec/config.py,sha256=LF4Zmu1vhJW7Je9Q-cwkRc3xP7Rhyy7Xnwj26Z6sv2g,4279
|
|
@@ -16,7 +16,7 @@ fsspec/gui.py,sha256=xBnHL2-r0LVwhDAtnHoPpXts7jd4Z32peawCJiI-7lI,13975
|
|
|
16
16
|
fsspec/json.py,sha256=65sQ0Y7mTj33u_Y4IId5up4abQ3bAel4E4QzbKMiQSg,3826
|
|
17
17
|
fsspec/mapping.py,sha256=m2ndB_gtRBXYmNJg0Ie1-BVR75TFleHmIQBzC-yWhjU,8343
|
|
18
18
|
fsspec/parquet.py,sha256=6ibAmG527L5JNFS0VO8BDNlxHdA3bVYqdByeiFgpUVM,19448
|
|
19
|
-
fsspec/registry.py,sha256=
|
|
19
|
+
fsspec/registry.py,sha256=5kz-61fkb29lgSLzXWvk67ft6ooeYJR24Hs1583rD8w,11570
|
|
20
20
|
fsspec/spec.py,sha256=l7ZEbgLsnrFuS-yrGl9re6ia1Yts1_10RqGV_mT-5P8,76032
|
|
21
21
|
fsspec/transaction.py,sha256=xliRG6U2Zf3khG4xcw9WiB-yAoqJSHEGK_VjHOdtgo0,2398
|
|
22
22
|
fsspec/utils.py,sha256=A11t25RnpiQ30RO6xeR0Qqlu3fGj8bnc40jg08tlYSI,22980
|
|
@@ -25,16 +25,16 @@ fsspec/implementations/arrow.py,sha256=721Dikne_lV_0tlgk9jyKmHL6W-5MT0h2LKGvOYQT
|
|
|
25
25
|
fsspec/implementations/asyn_wrapper.py,sha256=PNkYdHiLVWwk-GJok5O6dTnhPwDaSU9QTtBTE9CIRec,3082
|
|
26
26
|
fsspec/implementations/cache_mapper.py,sha256=W4wlxyPxZbSp9ItJ0pYRVBMh6bw9eFypgP6kUYuuiI4,2421
|
|
27
27
|
fsspec/implementations/cache_metadata.py,sha256=pcOJYcBQY5OaC7Yhw0F3wjg08QLYApGmoISCrbs59ks,8511
|
|
28
|
-
fsspec/implementations/cached.py,sha256=
|
|
28
|
+
fsspec/implementations/cached.py,sha256=2EqeHZi6TKZzr222ZyXHjuYBnx_1g_HWXj1CJBFsXbc,33173
|
|
29
29
|
fsspec/implementations/dask.py,sha256=CXZbJzIVOhKV8ILcxuy3bTvcacCueAbyQxmvAkbPkrk,4466
|
|
30
30
|
fsspec/implementations/data.py,sha256=LDLczxRh8h7x39Zjrd-GgzdQHr78yYxDlrv2C9Uxb5E,1658
|
|
31
31
|
fsspec/implementations/dbfs.py,sha256=XwpotuS_ncz3XK1dkUteww9GnTja7HoY91c0m4GUfwI,15092
|
|
32
32
|
fsspec/implementations/dirfs.py,sha256=f1sGnQ9Vf0xTxrXo4jDeBy4Qfq3RTqAEemqBSeb0hwY,12108
|
|
33
33
|
fsspec/implementations/ftp.py,sha256=sorsczLp_2J3ukONsbZY-11sRZP6H5a3V7XXf6o6ip0,11936
|
|
34
34
|
fsspec/implementations/git.py,sha256=4SElW9U5d3k3_ITlvUAx59Yk7XLNRTqkGa2C3hCUkWM,3754
|
|
35
|
-
fsspec/implementations/github.py,sha256=
|
|
35
|
+
fsspec/implementations/github.py,sha256=tvLepeDtBsFHYocsD7XS1W6r8wxaoK57Us3kHGisnjU,9146
|
|
36
36
|
fsspec/implementations/http.py,sha256=_gLt0yGbVOYWvE9pK81WCC-3TgbOMOKJYllBU72ALo8,30138
|
|
37
|
-
fsspec/implementations/http_sync.py,sha256=
|
|
37
|
+
fsspec/implementations/http_sync.py,sha256=UydDqSdUBdhiJ1KufzV8rKGrTftFR4QmNV0safILb8g,30133
|
|
38
38
|
fsspec/implementations/jupyter.py,sha256=B2uj7OEm7yIk-vRSsO37_ND0t0EBvn4B-Su43ibN4Pg,3811
|
|
39
39
|
fsspec/implementations/libarchive.py,sha256=5_I2DiLXwQ1JC8x-K7jXu-tBwhO9dj7tFLnb0bTnVMQ,7102
|
|
40
40
|
fsspec/implementations/local.py,sha256=g2iK8uWPGkSiI6bwmnIRXhJMQvTegCmXZ8Kb8ojhvAo,15543
|
|
@@ -53,7 +53,7 @@ fsspec/tests/abstract/mv.py,sha256=k8eUEBIrRrGMsBY5OOaDXdGnQUKGwDIfQyduB6YD3Ns,1
|
|
|
53
53
|
fsspec/tests/abstract/open.py,sha256=Fi2PBPYLbRqysF8cFm0rwnB41kMdQVYjq8cGyDXp3BU,329
|
|
54
54
|
fsspec/tests/abstract/pipe.py,sha256=LFzIrLCB5GLXf9rzFKJmE8AdG7LQ_h4bJo70r8FLPqM,402
|
|
55
55
|
fsspec/tests/abstract/put.py,sha256=7aih17OKB_IZZh1Mkq1eBDIjobhtMQmI8x-Pw-S_aZk,21201
|
|
56
|
-
fsspec-2025.3.
|
|
57
|
-
fsspec-2025.3.
|
|
58
|
-
fsspec-2025.3.
|
|
59
|
-
fsspec-2025.3.
|
|
56
|
+
fsspec-2025.3.1.dist-info/METADATA,sha256=CJaBlMGwxuW44faR38hNdBi2I1sydTS-KgC_hp6HzWc,11747
|
|
57
|
+
fsspec-2025.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
58
|
+
fsspec-2025.3.1.dist-info/licenses/LICENSE,sha256=LcNUls5TpzB5FcAIqESq1T53K0mzTN0ARFBnaRQH7JQ,1513
|
|
59
|
+
fsspec-2025.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|