fsspec 2024.5.0__py3-none-any.whl → 2024.6.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.
Files changed (76) hide show
  1. fsspec/_version.py +2 -2
  2. fsspec/caching.py +3 -2
  3. fsspec/compression.py +1 -1
  4. fsspec/generic.py +3 -0
  5. fsspec/implementations/cached.py +6 -16
  6. fsspec/implementations/dirfs.py +2 -0
  7. fsspec/implementations/github.py +12 -0
  8. fsspec/implementations/http.py +2 -1
  9. fsspec/implementations/reference.py +9 -0
  10. fsspec/implementations/smb.py +10 -0
  11. fsspec/json.py +121 -0
  12. fsspec/registry.py +24 -18
  13. fsspec/spec.py +119 -33
  14. fsspec/utils.py +1 -1
  15. {fsspec-2024.5.0.dist-info → fsspec-2024.6.1.dist-info}/METADATA +10 -5
  16. fsspec-2024.6.1.dist-info/RECORD +55 -0
  17. {fsspec-2024.5.0.dist-info → fsspec-2024.6.1.dist-info}/WHEEL +1 -1
  18. fsspec/implementations/tests/__init__.py +0 -0
  19. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_file_listing.yaml +0 -112
  20. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_mkdir.yaml +0 -582
  21. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_read_pyarrow_non_partitioned.yaml +0 -873
  22. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_read_range.yaml +0 -458
  23. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_read_range_chunked.yaml +0 -1355
  24. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_write_and_read.yaml +0 -795
  25. fsspec/implementations/tests/cassettes/test_dbfs/test_dbfs_write_pyarrow_non_partitioned.yaml +0 -613
  26. fsspec/implementations/tests/conftest.py +0 -39
  27. fsspec/implementations/tests/local/__init__.py +0 -0
  28. fsspec/implementations/tests/local/local_fixtures.py +0 -18
  29. fsspec/implementations/tests/local/local_test.py +0 -14
  30. fsspec/implementations/tests/memory/__init__.py +0 -0
  31. fsspec/implementations/tests/memory/memory_fixtures.py +0 -27
  32. fsspec/implementations/tests/memory/memory_test.py +0 -14
  33. fsspec/implementations/tests/out.zip +0 -0
  34. fsspec/implementations/tests/test_archive.py +0 -382
  35. fsspec/implementations/tests/test_arrow.py +0 -259
  36. fsspec/implementations/tests/test_cached.py +0 -1306
  37. fsspec/implementations/tests/test_common.py +0 -35
  38. fsspec/implementations/tests/test_dask.py +0 -29
  39. fsspec/implementations/tests/test_data.py +0 -20
  40. fsspec/implementations/tests/test_dbfs.py +0 -268
  41. fsspec/implementations/tests/test_dirfs.py +0 -588
  42. fsspec/implementations/tests/test_ftp.py +0 -178
  43. fsspec/implementations/tests/test_git.py +0 -76
  44. fsspec/implementations/tests/test_http.py +0 -577
  45. fsspec/implementations/tests/test_jupyter.py +0 -57
  46. fsspec/implementations/tests/test_libarchive.py +0 -33
  47. fsspec/implementations/tests/test_local.py +0 -1285
  48. fsspec/implementations/tests/test_memory.py +0 -382
  49. fsspec/implementations/tests/test_reference.py +0 -720
  50. fsspec/implementations/tests/test_sftp.py +0 -233
  51. fsspec/implementations/tests/test_smb.py +0 -139
  52. fsspec/implementations/tests/test_tar.py +0 -243
  53. fsspec/implementations/tests/test_webhdfs.py +0 -197
  54. fsspec/implementations/tests/test_zip.py +0 -134
  55. fsspec/tests/__init__.py +0 -0
  56. fsspec/tests/conftest.py +0 -188
  57. fsspec/tests/data/listing.html +0 -1
  58. fsspec/tests/test_api.py +0 -498
  59. fsspec/tests/test_async.py +0 -230
  60. fsspec/tests/test_caches.py +0 -255
  61. fsspec/tests/test_callbacks.py +0 -89
  62. fsspec/tests/test_compression.py +0 -164
  63. fsspec/tests/test_config.py +0 -129
  64. fsspec/tests/test_core.py +0 -466
  65. fsspec/tests/test_downstream.py +0 -40
  66. fsspec/tests/test_file.py +0 -200
  67. fsspec/tests/test_fuse.py +0 -147
  68. fsspec/tests/test_generic.py +0 -90
  69. fsspec/tests/test_gui.py +0 -23
  70. fsspec/tests/test_mapping.py +0 -228
  71. fsspec/tests/test_parquet.py +0 -140
  72. fsspec/tests/test_registry.py +0 -134
  73. fsspec/tests/test_spec.py +0 -1167
  74. fsspec/tests/test_utils.py +0 -478
  75. fsspec-2024.5.0.dist-info/RECORD +0 -111
  76. {fsspec-2024.5.0.dist-info → fsspec-2024.6.1.dist-info}/licenses/LICENSE +0 -0
fsspec/tests/test_core.py DELETED
@@ -1,466 +0,0 @@
1
- import os
2
- import pickle
3
- import tempfile
4
- import zipfile
5
- from contextlib import contextmanager
6
- from pathlib import Path
7
-
8
- import pytest
9
-
10
- import fsspec
11
- from fsspec.core import (
12
- OpenFile,
13
- OpenFiles,
14
- _expand_paths,
15
- expand_paths_if_needed,
16
- get_compression,
17
- get_fs_token_paths,
18
- open_files,
19
- open_local,
20
- )
21
-
22
-
23
- @contextmanager
24
- def tempzip(data={}):
25
- f = tempfile.mkstemp(suffix="zip")[1]
26
- with zipfile.ZipFile(f, mode="w") as z:
27
- for k, v in data.items():
28
- z.writestr(k, v)
29
- try:
30
- yield f
31
- finally:
32
- try:
33
- os.remove(f)
34
- except OSError:
35
- pass
36
-
37
-
38
- @pytest.mark.parametrize(
39
- "path, name_function, num, out",
40
- [
41
- [["apath"], None, 1, ["apath"]],
42
- ["apath.*.csv", None, 1, ["apath.0.csv"]],
43
- ["apath.*.csv", None, 2, ["apath.0.csv", "apath.1.csv"]],
44
- ["a*", lambda x: "abc"[x], 2, ["aa", "ab"]],
45
- ],
46
- )
47
- def test_expand_paths(path, name_function, num, out):
48
- assert _expand_paths(path, name_function, num) == out
49
-
50
-
51
- @pytest.mark.parametrize(
52
- "create_files, path, out",
53
- [
54
- [["apath"], "apath", ["apath"]],
55
- [["apath1"], "apath*", ["apath1"]],
56
- [["apath1", "apath2"], "apath*", ["apath1", "apath2"]],
57
- [["apath1", "apath2"], "apath[1]", ["apath1"]],
58
- [["apath1", "apath11"], "apath?", ["apath1"]],
59
- ],
60
- )
61
- def test_expand_paths_if_needed_in_read_mode(create_files, path, out):
62
- d = str(tempfile.mkdtemp())
63
- for f in create_files:
64
- f = os.path.join(d, f)
65
- open(f, "w").write("test")
66
-
67
- path = os.path.join(d, path)
68
-
69
- fs = fsspec.filesystem("file")
70
- res = expand_paths_if_needed([path], "r", 0, fs, None)
71
- assert [os.path.basename(p) for p in res] == out
72
-
73
-
74
- def test_expand_error():
75
- with pytest.raises(ValueError):
76
- _expand_paths("*.*", None, 1)
77
-
78
-
79
- @pytest.mark.parametrize("mode", ["w", "w+", "x", "x+"])
80
- def test_expand_fs_token_paths(mode):
81
- assert len(get_fs_token_paths("path", mode, num=2, expand=True)[-1]) == 2
82
-
83
-
84
- def test_openfile_api(m):
85
- m.open("somepath", "wb").write(b"data")
86
- of = OpenFile(m, "somepath")
87
- assert str(of) == "<OpenFile 'somepath'>"
88
- f = of.open()
89
- assert f.read() == b"data"
90
- f.close()
91
- with OpenFile(m, "somepath", mode="rt") as f:
92
- assert f.read() == "data"
93
-
94
-
95
- def test_openfile_open(m):
96
- of = OpenFile(m, "somepath", mode="wt")
97
- f = of.open()
98
- f.write("hello")
99
- assert m.size("somepath") == 0 # no flush yet
100
- of.close()
101
- assert m.size("somepath") == 5
102
-
103
-
104
- def test_open_local_w_cache():
105
- d1 = str(tempfile.mkdtemp())
106
- f1 = os.path.join(d1, "f1")
107
- open(f1, "w").write("test1")
108
- d2 = str(tempfile.mkdtemp())
109
- fn = open_local(f"simplecache://{f1}", cache_storage=d2, target_protocol="file")
110
- assert isinstance(fn, str)
111
- assert open(fn).read() == "test1"
112
- assert d2 in fn
113
-
114
-
115
- def test_open_local_w_magic():
116
- d1 = str(tempfile.mkdtemp())
117
- f1 = os.path.join(d1, "f1")
118
- open(f1, "w").write("test1")
119
- fn = open_local(os.path.join(d1, "f*"))
120
- assert len(fn) == 1
121
- assert isinstance(fn, list)
122
-
123
-
124
- def test_open_local_w_list_of_str():
125
- d1 = str(tempfile.mkdtemp())
126
- f1 = os.path.join(d1, "f1")
127
- open(f1, "w").write("test1")
128
- fn = open_local([f1, f1])
129
- assert len(fn) == 2
130
- assert isinstance(fn, list)
131
- assert all(isinstance(elem, str) for elem in fn)
132
-
133
-
134
- def test_open_local_w_path():
135
- d1 = str(tempfile.mkdtemp())
136
- f1 = os.path.join(d1, "f1")
137
- open(f1, "w").write("test1")
138
- p = Path(f1)
139
- fn = open_local(p)
140
- assert isinstance(fn, str)
141
-
142
-
143
- def test_open_local_w_list_of_path():
144
- d1 = str(tempfile.mkdtemp())
145
- f1 = os.path.join(d1, "f1")
146
- open(f1, "w").write("test1")
147
- p = Path(f1)
148
- fn = open_local([p, p])
149
- assert len(fn) == 2
150
- assert isinstance(fn, list)
151
- assert all(isinstance(elem, str) for elem in fn)
152
-
153
-
154
- def test_xz_lzma_compressions():
155
- pytest.importorskip("lzma")
156
- # Ensure that both 'xz' and 'lzma' compression names can be parsed
157
- assert get_compression("some_file.xz", "infer") == "xz"
158
- assert get_compression("some_file.xz", "xz") == "xz"
159
- assert get_compression("some_file.xz", "lzma") == "lzma"
160
-
161
-
162
- def test_list():
163
- here = os.path.abspath(os.path.dirname(__file__))
164
- flist = os.listdir(here)
165
- plist = [os.path.join(here, p).replace("\\", "/") for p in flist]
166
- of = open_files(plist)
167
- assert len(of) == len(flist)
168
- assert [f.path for f in of] == plist
169
-
170
-
171
- def test_open_expand(m, monkeypatch):
172
- m.pipe("/myfile", b"hello")
173
- with pytest.raises(FileNotFoundError, match="expand=True"):
174
- with fsspec.open("memory://my*", expand=False):
175
- pass
176
- with fsspec.open("memory://my*", expand=True) as f:
177
- assert f.path == "/myfile"
178
- monkeypatch.setattr(fsspec.core, "DEFAULT_EXPAND", True)
179
- with fsspec.open("memory://my*") as f:
180
- assert f.path == "/myfile"
181
-
182
-
183
- def test_pathobject(tmpdir):
184
- import pathlib
185
-
186
- tmpdir = str(tmpdir)
187
- plist_str = [os.path.join(str(tmpdir), f).replace("\\", "/") for f in ["a", "b"]]
188
- open(plist_str[0], "w").write("first file")
189
- open(plist_str[1], "w").write("second file")
190
- plist = [pathlib.Path(p) for p in plist_str]
191
- of = open_files(plist)
192
- assert len(of) == 2
193
- assert [f.path for f in of] == plist_str
194
-
195
- of = open_files(plist[0])
196
- assert len(of) == 1
197
- assert of[0].path == plist_str[0]
198
- with of[0] as f:
199
- assert f.read() == open(plist_str[0], "rb").read()
200
-
201
-
202
- def test_automkdir(tmpdir):
203
- dir = os.path.join(str(tmpdir), "a")
204
- of = fsspec.open(os.path.join(dir, "afile"), "w", auto_mkdir=False)
205
- with pytest.raises(IOError):
206
- with of:
207
- pass
208
-
209
- dir = os.path.join(str(tmpdir), "b")
210
- of = fsspec.open(os.path.join(dir, "bfile"), "w", auto_mkdir=True)
211
- with of:
212
- pass
213
-
214
- assert "bfile" in os.listdir(dir)
215
-
216
- dir = os.path.join(str(tmpdir), "c")
217
- with pytest.raises(FileNotFoundError):
218
- of = fsspec.open(os.path.join(dir, "bfile"), "w", auto_mkdir=False)
219
- with of:
220
- pass
221
-
222
-
223
- def test_automkdir_readonly(tmpdir):
224
- dir = os.path.join(str(tmpdir), "d")
225
- with pytest.raises(FileNotFoundError):
226
- of = fsspec.open(os.path.join(dir, "dfile"), "r")
227
- with of:
228
- pass
229
-
230
-
231
- def test_openfile_pickle_newline():
232
- # GH#318
233
- test = fsspec.open(__file__, newline=b"")
234
-
235
- pickled = pickle.dumps(test)
236
- restored = pickle.loads(pickled)
237
-
238
- assert test.newline == restored.newline
239
-
240
-
241
- def test_pickle_after_open_open():
242
- of = fsspec.open(__file__, mode="rt")
243
- test = of.open()
244
- of2 = pickle.loads(pickle.dumps(of))
245
- test2 = of2.open()
246
- test.close()
247
-
248
- assert not test2.closed
249
- of.close()
250
- of2.close()
251
-
252
-
253
- # Define a list of special glob characters.
254
- # Note that we need to escape some characters and also consider file system limitations.
255
- # '*' and '?' are excluded because they are not valid for many file systems.
256
- # Similarly, we're careful with '{', '}', and '@' as their special meaning is
257
- # context-specific and might not be considered special for filenames.
258
- # Add tests for more file systems and for more glob magic later
259
- glob_magic_characters = ["[", "]", "!"]
260
- if os.name != "nt":
261
- glob_magic_characters.extend(("*", "?")) # not valid on Windows
262
-
263
-
264
- @pytest.mark.parametrize("char", glob_magic_characters)
265
- def test_open_file_read_with_special_characters(tmp_path, char):
266
- # Create a filename incorporating the special character
267
- file_name = f"test{char}.txt"
268
- file_path = tmp_path / file_name
269
- expected_content = "Hello, world!"
270
-
271
- with open(file_path, "w") as f:
272
- f.write(expected_content)
273
-
274
- with fsspec.open(file_path, "r") as f:
275
- actual_content = f.read()
276
-
277
- assert actual_content == expected_content
278
-
279
-
280
- @pytest.mark.parametrize("char", glob_magic_characters)
281
- def test_open_files_read_with_special_characters(tmp_path, char):
282
- # Create a filename incorporating the special character
283
- file_name = f"test{char}.txt"
284
- file_path = tmp_path / file_name
285
- expected_content = "Hello, world!"
286
-
287
- with open(file_path, "w") as f:
288
- f.write(expected_content)
289
-
290
- with fsspec.open_files(file_path, "r")[0] as f:
291
- actual_content = f.read()
292
-
293
- assert actual_content == expected_content
294
-
295
-
296
- @pytest.mark.parametrize("char", glob_magic_characters)
297
- def test_open_file_write_with_special_characters(tmp_path, char, monkeypatch):
298
- # Create a filename incorporating the special character
299
- file_name = f"test{char}.txt"
300
- file_path = tmp_path / file_name
301
- expected_content = "Hello, world!"
302
-
303
- with fsspec.open(file_path, "w", expand=False) as f:
304
- f.write(expected_content)
305
-
306
- with open(file_path, "r") as f:
307
- actual_content = f.read()
308
-
309
- monkeypatch.setattr(fsspec.core, "DEFAULT_EXPAND", False)
310
- with fsspec.open(file_path, "w") as f:
311
- f.write(expected_content * 2)
312
-
313
- with open(file_path, "r") as f:
314
- f.read() == actual_content * 2
315
-
316
- assert actual_content == expected_content
317
-
318
-
319
- @pytest.mark.parametrize("char", glob_magic_characters)
320
- def test_open_files_read_with_special_characters(tmp_path, char):
321
- # Create a filename incorporating the special character
322
- file_name = f"test{char}.txt"
323
- file_path = tmp_path / file_name
324
- expected_content = "Hello, world!"
325
-
326
- with open(file_path, "w") as f:
327
- f.write(expected_content)
328
-
329
- with fsspec.open_files(
330
- urlpath=[os.fspath(file_path)], mode="r", auto_mkdir=False, expand=False
331
- )[0] as f:
332
- actual_content = f.read()
333
-
334
- assert actual_content == expected_content
335
-
336
-
337
- @pytest.mark.parametrize("char", glob_magic_characters)
338
- def test_open_files_write_with_special_characters(tmp_path, char):
339
- # Create a filename incorporating the special character
340
- file_name = f"test{char}.txt"
341
- file_path = tmp_path / file_name
342
- expected_content = "Hello, world!"
343
-
344
- with fsspec.open_files(
345
- urlpath=[os.fspath(file_path)], mode="w", auto_mkdir=False, expand=False
346
- )[0] as f:
347
- f.write(expected_content)
348
-
349
- with open(file_path, "r") as f:
350
- actual_content = f.read()
351
-
352
- assert actual_content == expected_content
353
-
354
-
355
- def test_mismatch():
356
- pytest.importorskip("s3fs")
357
- with pytest.raises(ValueError):
358
- open_files(["s3://test/path.csv", "/other/path.csv"])
359
-
360
-
361
- def test_url_kwargs_chain(ftp_writable):
362
- host, port, username, password = ftp_writable
363
- data = b"hello"
364
- with fsspec.open(
365
- "ftp:///afile", "wb", host=host, port=port, username=username, password=password
366
- ) as f:
367
- f.write(data)
368
-
369
- with fsspec.open(
370
- f"simplecache::ftp://{username}:{password}@{host}:{port}//afile", "rb"
371
- ) as f:
372
- assert f.read() == data
373
-
374
-
375
- def test_multi_context(tmpdir):
376
- fns = [os.path.join(tmpdir, fn) for fn in ["a", "b"]]
377
- files = open_files(fns, "wb")
378
- assert isinstance(files, OpenFiles)
379
- assert isinstance(files[0], OpenFile)
380
- assert len(files) == 2
381
- assert isinstance(files[:1], OpenFiles)
382
- assert len(files[:1]) == 1
383
- with files as of:
384
- assert len(of) == 2
385
- assert not of[0].closed
386
- assert of[0].name.endswith("a")
387
- assert of[0].closed
388
- assert repr(files) == "<List of 2 OpenFile instances>"
389
-
390
-
391
- def test_not_local():
392
- with pytest.raises(ValueError, match="attribute local_file=True"):
393
- open_local("memory://afile")
394
-
395
-
396
- def test_url_to_fs(ftp_writable):
397
- host, port, username, password = ftp_writable
398
- data = b"hello"
399
- with fsspec.open(f"ftp://{username}:{password}@{host}:{port}/afile", "wb") as f:
400
- f.write(data)
401
- fs, url = fsspec.core.url_to_fs(
402
- f"simplecache::ftp://{username}:{password}@{host}:{port}/afile"
403
- )
404
- assert url == "/afile"
405
- fs, url = fsspec.core.url_to_fs(f"ftp://{username}:{password}@{host}:{port}/afile")
406
- assert url == "/afile"
407
-
408
- with fsspec.open(f"ftp://{username}:{password}@{host}:{port}/afile.zip", "wb") as f:
409
- import zipfile
410
-
411
- with zipfile.ZipFile(f, "w") as z:
412
- with z.open("inner", "w") as f2:
413
- f2.write(b"hello")
414
- f.write(data)
415
-
416
- fs, url = fsspec.core.url_to_fs(
417
- f"zip://inner::ftp://{username}:{password}@{host}:{port}/afile.zip"
418
- )
419
- assert url == "inner"
420
- fs, url = fsspec.core.url_to_fs(
421
- f"simplecache::zip::ftp://{username}:{password}@{host}:{port}/afile.zip"
422
- )
423
- assert url == ""
424
-
425
-
426
- def test_target_protocol_options(ftp_writable):
427
- host, port, username, password = ftp_writable
428
- data = {"afile": b"hello"}
429
- options = {"host": host, "port": port, "username": username, "password": password}
430
- with tempzip(data) as lfile, fsspec.open(
431
- "ftp:///archive.zip", "wb", **options
432
- ) as f:
433
- f.write(open(lfile, "rb").read())
434
- with fsspec.open(
435
- "zip://afile",
436
- "rb",
437
- target_protocol="ftp",
438
- target_options=options,
439
- fo="archive.zip",
440
- ) as f:
441
- assert f.read() == data["afile"]
442
-
443
-
444
- def test_chained_url(ftp_writable):
445
- host, port, username, password = ftp_writable
446
- data = {"afile": b"hello"}
447
- cls = fsspec.get_filesystem_class("ftp")
448
- fs = cls(host=host, port=port, username=username, password=password)
449
- with tempzip(data) as lfile:
450
- fs.put_file(lfile, "archive.zip")
451
-
452
- urls = [
453
- "zip://afile",
454
- "zip://afile::simplecache",
455
- "simplecache::zip://afile",
456
- "simplecache::zip://afile::simplecache",
457
- ]
458
- for url in urls:
459
- url += f"::ftp://{username}:{password}@{host}:{port}/archive.zip"
460
- with fsspec.open(url, "rb") as f:
461
- assert f.read() == data["afile"]
462
-
463
-
464
- def test_automkdir_local():
465
- fs, _ = fsspec.core.url_to_fs("file://", auto_mkdir=True)
466
- assert fs.auto_mkdir is True
@@ -1,40 +0,0 @@
1
- import pytest
2
-
3
- pytest.importorskip("s3fs")
4
- pytest.importorskip("moto")
5
-
6
- try:
7
- from s3fs.tests.test_s3fs import ( # noqa: E402,F401
8
- endpoint_uri,
9
- s3,
10
- s3_base,
11
- test_bucket_name,
12
- )
13
- except ImportError:
14
- pytest.skip("s3 tests not available.")
15
-
16
- so = {"anon": False, "client_kwargs": {"endpoint_url": endpoint_uri}}
17
-
18
-
19
- def test_pandas(s3):
20
- pd = pytest.importorskip("pandas")
21
- df = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
22
- df.to_csv(f"s3://{test_bucket_name}/a.csv", storage_options=so)
23
- df2 = pd.read_csv(f"s3://{test_bucket_name}/a.csv", storage_options=so)
24
-
25
- assert df.a.equals(df2.a)
26
-
27
-
28
- def test_xarray_zarr(s3):
29
- xr = pytest.importorskip("xarray")
30
- pytest.importorskip("zarr")
31
- import numpy as np
32
-
33
- x = np.arange(5)
34
- xarr = xr.DataArray(x)
35
- ds = xr.Dataset({"x": xarr})
36
- ds.to_zarr(f"s3://{test_bucket_name}/a.zarr", storage_options=so)
37
-
38
- ds2 = xr.open_zarr(f"s3://{test_bucket_name}/a.zarr", storage_options=so)
39
-
40
- assert (ds.x == ds2.x).all()
fsspec/tests/test_file.py DELETED
@@ -1,200 +0,0 @@
1
- """Tests abstract buffered file API, using FTP implementation"""
2
-
3
- import pickle
4
-
5
- import pytest
6
-
7
- from fsspec.implementations.tests.test_ftp import FTPFileSystem
8
-
9
- data = b"hello" * 10000
10
-
11
-
12
- def test_pickle(ftp_writable):
13
- host, port, user, pw = ftp_writable
14
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
15
-
16
- f = ftp.open("/out", "rb")
17
-
18
- f2 = pickle.loads(pickle.dumps(f))
19
- assert f == f2
20
-
21
-
22
- def test_file_read_attributes(ftp_writable):
23
- host, port, user, pw = ftp_writable
24
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
25
-
26
- f = ftp.open("/out", "rb")
27
- assert f.info()["size"] == len(data)
28
- assert f.tell() == 0
29
- assert f.seekable()
30
- assert f.readable()
31
- assert not f.writable()
32
- out = bytearray(len(data))
33
-
34
- assert f.read() == data
35
- assert f.read() == b""
36
- f.seek(0)
37
- assert f.readuntil(b"l") == b"hel"
38
- assert f.tell() == 3
39
-
40
- f.readinto1(out)
41
- assert out[:-3] == data[3:]
42
- with pytest.raises(ValueError):
43
- f.write(b"")
44
- f.close()
45
- with pytest.raises(ValueError):
46
- f.read()(b"")
47
-
48
-
49
- def test_seek(ftp_writable):
50
- host, port, user, pw = ftp_writable
51
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
52
-
53
- f = ftp.open("/out", "rb")
54
-
55
- assert f.seek(-10, 2) == len(data) - 10
56
- assert f.tell() == len(data) - 10
57
- assert f.seek(-1, 1) == len(data) - 11
58
- with pytest.raises(ValueError):
59
- f.seek(-1)
60
- with pytest.raises(ValueError):
61
- f.seek(0, 7)
62
-
63
-
64
- def test_file_idempotent(ftp_writable):
65
- host, port, user, pw = ftp_writable
66
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
67
-
68
- f = ftp.open("/out", "rb")
69
- f2 = ftp.open("/out", "rb")
70
- assert hash(f) == hash(f2)
71
- assert f == f2
72
- ftp.touch("/out2")
73
- f2 = ftp.open("/out2", "rb")
74
- assert hash(f2) != hash(f)
75
- assert f != f2
76
- f2 = ftp.open("/out", "wb")
77
- assert hash(f2) != hash(f)
78
-
79
-
80
- def test_file_text_attributes(ftp_writable):
81
- host, port, user, pw = ftp_writable
82
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
83
-
84
- data = b"hello\n" * 1000
85
- with ftp.open("/out2", "wb") as f:
86
- f.write(data)
87
-
88
- f = ftp.open("/out2", "rb")
89
- assert f.readline() == b"hello\n"
90
- f.seek(0)
91
- assert list(f) == [d + b"\n" for d in data.split()]
92
- f.seek(0)
93
- assert f.readlines() == [d + b"\n" for d in data.split()]
94
-
95
- f = ftp.open("/out2", "rt")
96
- assert f.readline() == "hello\n"
97
- assert f.encoding
98
-
99
-
100
- def test_file_write_attributes(ftp_writable):
101
- host, port, user, pw = ftp_writable
102
- ftp = FTPFileSystem(host=host, port=port, username=user, password=pw)
103
- f = ftp.open("/out2", "wb")
104
- with pytest.raises(ValueError):
105
- f.info()
106
- with pytest.raises(OSError):
107
- f.seek(0)
108
- with pytest.raises(ValueError):
109
- f.read(0)
110
- assert not f.readable()
111
- assert f.writable()
112
-
113
- f.flush() # no-op
114
-
115
- assert f.write(b"hello") == 5
116
- assert f.write(b"hello") == 5
117
- assert not f.closed
118
- f.close()
119
- assert f.closed
120
- with pytest.raises(ValueError):
121
- f.write(b"")
122
- with pytest.raises(ValueError):
123
- f.flush()
124
-
125
-
126
- def test_midread_cache(ftp_writable):
127
- host, port, user, pw = ftp_writable
128
- fs = FTPFileSystem(host=host, port=port, username=user, password=pw)
129
- fn = "/myfile"
130
- with fs.open(fn, "wb") as f:
131
- f.write(b"a" * 175627146)
132
- with fs.open(fn, "rb") as f:
133
- f.seek(175561610)
134
- d1 = f.read(65536)
135
- assert len(d1) == 65536
136
-
137
- f.seek(4)
138
- size = 17562198
139
- d2 = f.read(size)
140
- assert len(d2) == size
141
-
142
- f.seek(17562288)
143
- size = 17562187
144
- d3 = f.read(size)
145
- assert len(d3) == size
146
-
147
-
148
- def test_read_block(ftp_writable):
149
- # not the same as test_read_block in test_utils, this depends on the
150
- # behaviour of the bytest caching
151
- from fsspec.utils import read_block
152
-
153
- host, port, user, pw = ftp_writable
154
- fs = FTPFileSystem(host=host, port=port, username=user, password=pw)
155
- fn = "/myfile"
156
- with fs.open(fn, "wb") as f:
157
- f.write(b"a,b\n1,2")
158
- f = fs.open(fn, "rb", cache_type="bytes")
159
- assert read_block(f, 0, 6400, b"\n") == b"a,b\n1,2"
160
-
161
-
162
- def test_with_gzip(ftp_writable):
163
- import gzip
164
-
165
- data = b"some compressible stuff"
166
- host, port, user, pw = ftp_writable
167
- fs = FTPFileSystem(host=host, port=port, username=user, password=pw)
168
- fn = "/myfile"
169
- with fs.open(fn, "wb") as f:
170
- gf = gzip.GzipFile(fileobj=f, mode="w")
171
- gf.write(data)
172
- gf.close()
173
- with fs.open(fn, "rb") as f:
174
- gf = gzip.GzipFile(fileobj=f, mode="r")
175
- assert gf.read() == data
176
-
177
-
178
- def test_auto_compression(m):
179
- fs = m
180
- with fs.open("myfile.gz", mode="wt", compression="infer") as f:
181
- f.write("text")
182
- with fs.open("myfile.gz", mode="rt", compression="infer") as f:
183
- assert f.read() == "text"
184
-
185
-
186
- def test_with_zip(ftp_writable):
187
- import zipfile
188
-
189
- data = b"hello zip"
190
- host, port, user, pw = ftp_writable
191
- fs = FTPFileSystem(host=host, port=port, username=user, password=pw)
192
- fn = "/myfile.zip"
193
- inner_file = "test.txt"
194
- with fs.open(fn, "wb") as f:
195
- zf = zipfile.ZipFile(f, mode="w")
196
- zf.writestr(inner_file, data)
197
- zf.close()
198
- with fs.open(fn, "rb") as f:
199
- zf = zipfile.ZipFile(f, mode="r")
200
- assert zf.read(inner_file) == data