fsspec 2025.12.0__py3-none-any.whl → 2026.1.0__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 CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2025.12.0'
32
- __version_tuple__ = version_tuple = (2025, 12, 0)
31
+ __version__ = version = '2026.1.0'
32
+ __version_tuple__ = version_tuple = (2026, 1, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
fsspec/compression.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Helper functions for a standard streaming compression API"""
2
2
 
3
+ import sys
3
4
  from zipfile import ZipFile
4
5
 
5
6
  import fsspec.utils
@@ -155,26 +156,14 @@ except ImportError:
155
156
  pass
156
157
 
157
158
  try:
158
- # zstd in the standard library for python >= 3.14
159
- from compression.zstd import ZstdFile
160
-
161
- register_compression("zstd", ZstdFile, "zst")
159
+ if sys.version_info >= (3, 14):
160
+ from compression import zstd
161
+ else:
162
+ from backports import zstd
162
163
 
164
+ register_compression("zstd", zstd.ZstdFile, "zst")
163
165
  except ImportError:
164
- try:
165
- import zstandard as zstd
166
-
167
- def zstandard_file(infile, mode="rb"):
168
- if "r" in mode:
169
- cctx = zstd.ZstdDecompressor()
170
- return cctx.stream_reader(infile)
171
- else:
172
- cctx = zstd.ZstdCompressor(level=10)
173
- return cctx.stream_writer(infile)
174
-
175
- register_compression("zstd", zstandard_file, "zst")
176
- except ImportError:
177
- pass
166
+ pass
178
167
 
179
168
 
180
169
  def available_compressions():
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import ssl
2
3
  import uuid
3
4
  from ftplib import FTP, FTP_TLS, Error, error_perm
4
5
  from typing import Any
@@ -6,6 +7,37 @@ from typing import Any
6
7
  from ..spec import AbstractBufferedFile, AbstractFileSystem
7
8
  from ..utils import infer_storage_options, isfilelike
8
9
 
10
+ SECURITY_PROTOCOL_MAP = {
11
+ "tls": ssl.PROTOCOL_TLS,
12
+ "tlsv1": ssl.PROTOCOL_TLSv1,
13
+ "tlsv1_1": ssl.PROTOCOL_TLSv1_1,
14
+ "tlsv1_2": ssl.PROTOCOL_TLSv1_2,
15
+ "sslv23": ssl.PROTOCOL_SSLv23,
16
+ }
17
+
18
+
19
+ class ImplicitFTPTLS(FTP_TLS):
20
+ """
21
+ FTP_TLS subclass that automatically wraps sockets in SSL
22
+ to support implicit FTPS.
23
+ """
24
+
25
+ def __init__(self, *args, **kwargs):
26
+ super().__init__(*args, **kwargs)
27
+ self._sock = None
28
+
29
+ @property
30
+ def sock(self):
31
+ """Return the socket."""
32
+ return self._sock
33
+
34
+ @sock.setter
35
+ def sock(self, value):
36
+ """When modifying the socket, ensure that it is ssl wrapped."""
37
+ if value is not None and not isinstance(value, ssl.SSLSocket):
38
+ value = self.context.wrap_socket(value)
39
+ self._sock = value
40
+
9
41
 
10
42
  class FTPFileSystem(AbstractFileSystem):
11
43
  """A filesystem over classic FTP"""
@@ -55,8 +87,14 @@ class FTPFileSystem(AbstractFileSystem):
55
87
  Timeout of the ftp connection in seconds
56
88
  encoding: str
57
89
  Encoding to use for directories and filenames in FTP connection
58
- tls: bool
59
- Use FTP-TLS, by default False
90
+ tls: bool or str
91
+ Enable FTP-TLS for secure connections:
92
+ - False: Plain FTP (default)
93
+ - True: Explicit TLS (FTPS with AUTH TLS command)
94
+ - "tls": Auto-negotiate highest protocol
95
+ - "tlsv1": TLS v1.0
96
+ - "tlsv1_1": TLS v1.1
97
+ - "tlsv1_2": TLS v1.2
60
98
  """
61
99
  super().__init__(**kwargs)
62
100
  self.host = host
@@ -71,15 +109,27 @@ class FTPFileSystem(AbstractFileSystem):
71
109
  self.blocksize = 2**16
72
110
  self.tls = tls
73
111
  self._connect()
74
- if self.tls:
112
+ if isinstance(self.tls, bool) and self.tls:
75
113
  self.ftp.prot_p()
76
114
 
77
115
  def _connect(self):
116
+ security = None
78
117
  if self.tls:
79
- ftp_cls = FTP_TLS
118
+ if isinstance(self.tls, str):
119
+ ftp_cls = ImplicitFTPTLS
120
+ security = SECURITY_PROTOCOL_MAP.get(
121
+ self.tls,
122
+ f"Not supported {self.tls} protocol",
123
+ )
124
+ if isinstance(security, str):
125
+ raise ValueError(security)
126
+ else:
127
+ ftp_cls = FTP_TLS
80
128
  else:
81
129
  ftp_cls = FTP
82
130
  self.ftp = ftp_cls(timeout=self.timeout, encoding=self.encoding)
131
+ if security:
132
+ self.ftp.ssl_version = security
83
133
  self.ftp.connect(self.host, self.port)
84
134
  self.ftp.login(*self.cred)
85
135
 
@@ -166,6 +166,10 @@ class LocalFileSystem(AbstractFileSystem):
166
166
  """
167
167
  path1 = self._strip_protocol(path1)
168
168
  path2 = self._strip_protocol(path2)
169
+
170
+ if self.auto_mkdir:
171
+ self.makedirs(self._parent(path2), exist_ok=True)
172
+
169
173
  shutil.move(path1, path2)
170
174
 
171
175
  def link(self, src, dst, **kwargs):
fsspec/registry.py CHANGED
@@ -189,7 +189,7 @@ known_implementations = {
189
189
  },
190
190
  "pyscript": {
191
191
  "class": "pyscript_fsspec_client.client.PyscriptFileSystem",
192
- "err": "Install requests (cpython) or run in pyscript",
192
+ "err": "This only runs in a pyscript context",
193
193
  },
194
194
  "reference": {"class": "fsspec.implementations.reference.ReferenceFileSystem"},
195
195
  "root": {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fsspec
3
- Version: 2025.12.0
3
+ Version: 2026.1.0
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/
@@ -49,7 +49,7 @@ Requires-Dist: distributed; extra == 'full'
49
49
  Requires-Dist: dropbox; extra == 'full'
50
50
  Requires-Dist: dropboxdrivefs; extra == 'full'
51
51
  Requires-Dist: fusepy; extra == 'full'
52
- Requires-Dist: gcsfs; extra == 'full'
52
+ Requires-Dist: gcsfs>2024.2.0; extra == 'full'
53
53
  Requires-Dist: libarchive-c; extra == 'full'
54
54
  Requires-Dist: ocifs; extra == 'full'
55
55
  Requires-Dist: panel; extra == 'full'
@@ -57,7 +57,7 @@ Requires-Dist: paramiko; extra == 'full'
57
57
  Requires-Dist: pyarrow>=1; extra == 'full'
58
58
  Requires-Dist: pygit2; extra == 'full'
59
59
  Requires-Dist: requests; extra == 'full'
60
- Requires-Dist: s3fs; extra == 'full'
60
+ Requires-Dist: s3fs>2024.2.0; extra == 'full'
61
61
  Requires-Dist: smbprotocol; extra == 'full'
62
62
  Requires-Dist: tqdm; extra == 'full'
63
63
  Provides-Extra: fuse
@@ -108,6 +108,7 @@ Requires-Dist: xarray; extra == 'test-downstream'
108
108
  Provides-Extra: test-full
109
109
  Requires-Dist: adlfs; extra == 'test-full'
110
110
  Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == 'test-full'
111
+ Requires-Dist: backports-zstd; (python_version < '3.14') and extra == 'test-full'
111
112
  Requires-Dist: cloudpickle; extra == 'test-full'
112
113
  Requires-Dist: dask; extra == 'test-full'
113
114
  Requires-Dist: distributed; extra == 'test-full'
@@ -143,7 +144,6 @@ Requires-Dist: smbprotocol; extra == 'test-full'
143
144
  Requires-Dist: tqdm; extra == 'test-full'
144
145
  Requires-Dist: urllib3; extra == 'test-full'
145
146
  Requires-Dist: zarr; extra == 'test-full'
146
- Requires-Dist: zstandard; (python_version < '3.14') and extra == 'test-full'
147
147
  Provides-Extra: tqdm
148
148
  Requires-Dist: tqdm; extra == 'tqdm'
149
149
  Description-Content-Type: text/markdown
@@ -1,10 +1,10 @@
1
1
  fsspec/__init__.py,sha256=L7qwNBU1iMNQd8Of87HYSNFT9gWlNMSESaJC8fY0AaQ,2053
2
- fsspec/_version.py,sha256=u_WCUBrOC78o9bqe-21i1S8FKT43ei4dqyL4oKUga9g,712
2
+ fsspec/_version.py,sha256=u-dFB5QwBm8gDrxy5VP5UIh5ycEbPIDyQZ0EuPEDRHs,710
3
3
  fsspec/archive.py,sha256=vM6t_lgV6lBWbBYwpm3S4ofBQFQxUPr5KkDQrrQcQro,2411
4
4
  fsspec/asyn.py,sha256=LP_OicTWXmKHe31wBoYs2MrrNf8rmlhjVeGg5AqvVy8,36630
5
5
  fsspec/caching.py,sha256=B2xeDz9-VDgr_dDeVOTNRq3vaS9zVUe0nxtOBgsrjUk,34260
6
6
  fsspec/callbacks.py,sha256=BDIwLzK6rr_0V5ch557fSzsivCElpdqhXr5dZ9Te-EE,9210
7
- fsspec/compression.py,sha256=gBK2MV_oTFVW2XDq8bZVbYQKYrl6JDUou6_-kyvmxuk,5086
7
+ fsspec/compression.py,sha256=jwxtX_2hPr97s53W89ywkxH3wm-ZGiUoUyCCsFA4V1Y,4698
8
8
  fsspec/config.py,sha256=LF4Zmu1vhJW7Je9Q-cwkRc3xP7Rhyy7Xnwj26Z6sv2g,4279
9
9
  fsspec/conftest.py,sha256=uWfm_Qs5alPRxOhRpDfQ0-1jqSJ54pni4y96IxOREXM,3446
10
10
  fsspec/core.py,sha256=lc7XSnZU6_C6xljp7Z_xEGN3V7704hbeQLkxvPP0wds,24173
@@ -16,7 +16,7 @@ fsspec/gui.py,sha256=CQ7QsrTpaDlWSLNOpwNoJc7khOcYXIZxmrAJN9bHWQU,14002
16
16
  fsspec/json.py,sha256=4EBZ-xOmRiyxmIqPIwxmDImosRQ7io7qBM2xjJPsEE4,3768
17
17
  fsspec/mapping.py,sha256=m2ndB_gtRBXYmNJg0Ie1-BVR75TFleHmIQBzC-yWhjU,8343
18
18
  fsspec/parquet.py,sha256=vpOuoxg0y0iS2yoiXeAUcWB0n-wct2x2L6Vmn_O-hRQ,20668
19
- fsspec/registry.py,sha256=Kvv7NEqvIDhI2PXoYmwi4Z9RHAjrLMhGRu3m492801s,12157
19
+ fsspec/registry.py,sha256=o7EGl8TEaLkcwN53X_103arzuzJeeOoVaNUWnPiXgf0,12148
20
20
  fsspec/spec.py,sha256=Ym-Ust6LRjHgbhrmvNqwOBZxoVnaw3g3xHXMZGHx_xg,77692
21
21
  fsspec/transaction.py,sha256=xliRG6U2Zf3khG4xcw9WiB-yAoqJSHEGK_VjHOdtgo0,2398
22
22
  fsspec/utils.py,sha256=5DOxB_eE-wNHwrc6zp3h-oMp5mCLw4tsQZqqPTjLDmM,23136
@@ -31,7 +31,7 @@ fsspec/implementations/dask.py,sha256=CXZbJzIVOhKV8ILcxuy3bTvcacCueAbyQxmvAkbPkr
31
31
  fsspec/implementations/data.py,sha256=IhOGDkacYp5gkl9jhEu4msQfZPb0gS5Q_ml7Mbr6dgQ,1627
32
32
  fsspec/implementations/dbfs.py,sha256=1cvvC6KBWOb8pBVpc01xavVbEPXO1xsgZvPD7H73M9k,16217
33
33
  fsspec/implementations/dirfs.py,sha256=VNj6gPMfmmLPK4wxbtxt7mUqW7xkh2XDgMmEmSK_E1c,12166
34
- fsspec/implementations/ftp.py,sha256=bzL_TgH77nMMtTMewRGkbq4iObSHGu7YoMRCXBH4nrc,11639
34
+ fsspec/implementations/ftp.py,sha256=fJhaMIKq2RvzYlLwG3bewy2jq4iRqjVt1aIpwtUIRwI,13235
35
35
  fsspec/implementations/gist.py,sha256=Y6jTDrE-wuTwvpPyAQDuuOMBGxlajafKWoB1_yX6jdY,8528
36
36
  fsspec/implementations/git.py,sha256=qBDWMz5LNllPqVjr5jf_1FuNha4P5lyQI3IlhYg-wUE,3731
37
37
  fsspec/implementations/github.py,sha256=aCsZL8UvXZgdkcB1RUs3DdLeNrjLKcFsFYeQFDWbBFo,11653
@@ -39,7 +39,7 @@ fsspec/implementations/http.py,sha256=-AV5qeNpBWqnsmgnIO9Ily9B6--SR4sQJ7G4cBHarG
39
39
  fsspec/implementations/http_sync.py,sha256=UmBqd938ebwVjYgVtzg-ysG3ZoGhIJw0wFtQAfxV3Aw,30332
40
40
  fsspec/implementations/jupyter.py,sha256=q1PlQ66AAswGFyr8MFKWyobaV2YekMWRtqENBDQtD28,4002
41
41
  fsspec/implementations/libarchive.py,sha256=SpIA1F-zf7kb2-VYUVuhMrXTBOhBxUXKgEW1RaAdDoA,7098
42
- fsspec/implementations/local.py,sha256=DQeK7jRGv4_mJAweLKALO5WzIIkjXxZ_jRvwQ_xadSA,16936
42
+ fsspec/implementations/local.py,sha256=ERDUdXdRI8AvRX06icXaDKwO-hcQgivc7EorqnayFFM,17028
43
43
  fsspec/implementations/memory.py,sha256=TDdLtSPWXxZKrrVGwmc3uS3oK_2mlcVTk2BiqR8IeII,10507
44
44
  fsspec/implementations/reference.py,sha256=xSUpB8o_QFAZiVJE2dt78QZMCUMLo5TaJ27e5DwDAfg,48814
45
45
  fsspec/implementations/sftp.py,sha256=L9pZOa6eLUWfJNtxkxeG2YI96SQwrM5Hj6ocyUZXUbg,5923
@@ -55,7 +55,7 @@ fsspec/tests/abstract/mv.py,sha256=k8eUEBIrRrGMsBY5OOaDXdGnQUKGwDIfQyduB6YD3Ns,1
55
55
  fsspec/tests/abstract/open.py,sha256=Fi2PBPYLbRqysF8cFm0rwnB41kMdQVYjq8cGyDXp3BU,329
56
56
  fsspec/tests/abstract/pipe.py,sha256=LFzIrLCB5GLXf9rzFKJmE8AdG7LQ_h4bJo70r8FLPqM,402
57
57
  fsspec/tests/abstract/put.py,sha256=7aih17OKB_IZZh1Mkq1eBDIjobhtMQmI8x-Pw-S_aZk,21201
58
- fsspec-2025.12.0.dist-info/METADATA,sha256=Fm2bIMio0NYy1EdMfxgGq4OE2kE5nt1qZDaDYbOuC0M,10401
59
- fsspec-2025.12.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
60
- fsspec-2025.12.0.dist-info/licenses/LICENSE,sha256=LcNUls5TpzB5FcAIqESq1T53K0mzTN0ARFBnaRQH7JQ,1513
61
- fsspec-2025.12.0.dist-info/RECORD,,
58
+ fsspec-2026.1.0.dist-info/METADATA,sha256=8mMtsh4ST3Onc1RmJWIyCY6ih2YzdtmD5iAhvaS2wnM,10423
59
+ fsspec-2026.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
60
+ fsspec-2026.1.0.dist-info/licenses/LICENSE,sha256=LcNUls5TpzB5FcAIqESq1T53K0mzTN0ARFBnaRQH7JQ,1513
61
+ fsspec-2026.1.0.dist-info/RECORD,,