fsspec 2023.9.2__tar.gz → 2023.12.0__tar.gz

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 (64) hide show
  1. {fsspec-2023.9.2/fsspec.egg-info → fsspec-2023.12.0}/PKG-INFO +47 -2
  2. {fsspec-2023.9.2 → fsspec-2023.12.0}/README.md +1 -0
  3. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/__init__.py +6 -1
  4. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/_version.py +4 -4
  5. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/archive.py +1 -1
  6. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/asyn.py +35 -45
  7. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/caching.py +161 -90
  8. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/compression.py +2 -4
  9. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/core.py +19 -6
  10. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/fuse.py +2 -2
  11. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/generic.py +5 -1
  12. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/gui.py +4 -4
  13. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/cached.py +105 -25
  14. fsspec-2023.12.0/fsspec/implementations/data.py +48 -0
  15. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/ftp.py +6 -6
  16. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/git.py +3 -3
  17. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/github.py +3 -7
  18. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/http.py +34 -47
  19. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/jupyter.py +5 -5
  20. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/libarchive.py +1 -2
  21. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/local.py +8 -4
  22. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/memory.py +1 -1
  23. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/reference.py +67 -25
  24. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/sftp.py +11 -11
  25. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/smb.py +4 -5
  26. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/webhdfs.py +28 -8
  27. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/zip.py +2 -2
  28. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/mapping.py +2 -2
  29. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/registry.py +8 -6
  30. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/spec.py +41 -55
  31. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/tests/abstract/common.py +5 -5
  32. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/transaction.py +8 -4
  33. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/utils.py +204 -37
  34. {fsspec-2023.9.2 → fsspec-2023.12.0/fsspec.egg-info}/PKG-INFO +47 -2
  35. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec.egg-info/SOURCES.txt +1 -0
  36. {fsspec-2023.9.2 → fsspec-2023.12.0}/pyproject.toml +1 -1
  37. {fsspec-2023.9.2 → fsspec-2023.12.0}/setup.cfg +8 -2
  38. {fsspec-2023.9.2 → fsspec-2023.12.0}/versioneer.py +418 -208
  39. {fsspec-2023.9.2 → fsspec-2023.12.0}/LICENSE +0 -0
  40. {fsspec-2023.9.2 → fsspec-2023.12.0}/MANIFEST.in +0 -0
  41. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/callbacks.py +0 -0
  42. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/config.py +0 -0
  43. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/conftest.py +0 -0
  44. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/dircache.py +0 -0
  45. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/exceptions.py +0 -0
  46. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/__init__.py +0 -0
  47. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/arrow.py +0 -0
  48. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/cache_mapper.py +0 -0
  49. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/cache_metadata.py +0 -0
  50. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/dask.py +0 -0
  51. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/dbfs.py +0 -0
  52. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/dirfs.py +0 -0
  53. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/implementations/tar.py +0 -0
  54. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/parquet.py +0 -0
  55. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/tests/abstract/__init__.py +0 -0
  56. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/tests/abstract/copy.py +0 -0
  57. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/tests/abstract/get.py +0 -0
  58. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec/tests/abstract/put.py +0 -0
  59. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec.egg-info/dependency_links.txt +0 -0
  60. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec.egg-info/not-zip-safe +0 -0
  61. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec.egg-info/requires.txt +0 -0
  62. {fsspec-2023.9.2 → fsspec-2023.12.0}/fsspec.egg-info/top_level.txt +0 -0
  63. {fsspec-2023.9.2 → fsspec-2023.12.0}/requirements.txt +0 -0
  64. {fsspec-2023.9.2 → fsspec-2023.12.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fsspec
3
- Version: 2023.9.2
3
+ Version: 2023.12.0
4
4
  Summary: File-system specification
5
5
  Home-page: https://github.com/fsspec/filesystem_spec
6
6
  Maintainer: Martin Durant
@@ -19,30 +19,74 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
+ License-File: LICENSE
22
23
  Provides-Extra: entrypoints
23
24
  Provides-Extra: abfs
25
+ Requires-Dist: adlfs; extra == "abfs"
24
26
  Provides-Extra: adl
27
+ Requires-Dist: adlfs; extra == "adl"
25
28
  Provides-Extra: dask
29
+ Requires-Dist: dask; extra == "dask"
30
+ Requires-Dist: distributed; extra == "dask"
26
31
  Provides-Extra: dropbox
32
+ Requires-Dist: dropboxdrivefs; extra == "dropbox"
33
+ Requires-Dist: requests; extra == "dropbox"
34
+ Requires-Dist: dropbox; extra == "dropbox"
27
35
  Provides-Extra: gcs
36
+ Requires-Dist: gcsfs; extra == "gcs"
28
37
  Provides-Extra: git
38
+ Requires-Dist: pygit2; extra == "git"
29
39
  Provides-Extra: github
40
+ Requires-Dist: requests; extra == "github"
30
41
  Provides-Extra: gs
42
+ Requires-Dist: gcsfs; extra == "gs"
31
43
  Provides-Extra: hdfs
44
+ Requires-Dist: pyarrow>=1; extra == "hdfs"
32
45
  Provides-Extra: arrow
46
+ Requires-Dist: pyarrow>=1; extra == "arrow"
33
47
  Provides-Extra: http
48
+ Requires-Dist: requests; extra == "http"
49
+ Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == "http"
34
50
  Provides-Extra: sftp
51
+ Requires-Dist: paramiko; extra == "sftp"
35
52
  Provides-Extra: s3
53
+ Requires-Dist: s3fs; extra == "s3"
36
54
  Provides-Extra: oci
55
+ Requires-Dist: ocifs; extra == "oci"
37
56
  Provides-Extra: smb
57
+ Requires-Dist: smbprotocol; extra == "smb"
38
58
  Provides-Extra: ssh
59
+ Requires-Dist: paramiko; extra == "ssh"
39
60
  Provides-Extra: fuse
61
+ Requires-Dist: fusepy; extra == "fuse"
40
62
  Provides-Extra: libarchive
63
+ Requires-Dist: libarchive-c; extra == "libarchive"
41
64
  Provides-Extra: gui
65
+ Requires-Dist: panel; extra == "gui"
42
66
  Provides-Extra: tqdm
67
+ Requires-Dist: tqdm; extra == "tqdm"
43
68
  Provides-Extra: full
69
+ Requires-Dist: adlfs; extra == "full"
70
+ Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == "full"
71
+ Requires-Dist: dask; extra == "full"
72
+ Requires-Dist: distributed; extra == "full"
73
+ Requires-Dist: dropbox; extra == "full"
74
+ Requires-Dist: dropboxdrivefs; extra == "full"
75
+ Requires-Dist: fusepy; extra == "full"
76
+ Requires-Dist: gcsfs; extra == "full"
77
+ Requires-Dist: libarchive-c; extra == "full"
78
+ Requires-Dist: ocifs; extra == "full"
79
+ Requires-Dist: panel; extra == "full"
80
+ Requires-Dist: paramiko; extra == "full"
81
+ Requires-Dist: pyarrow>=1; extra == "full"
82
+ Requires-Dist: pygit2; extra == "full"
83
+ Requires-Dist: requests; extra == "full"
84
+ Requires-Dist: s3fs; extra == "full"
85
+ Requires-Dist: smbprotocol; extra == "full"
86
+ Requires-Dist: tqdm; extra == "full"
44
87
  Provides-Extra: devel
45
- License-File: LICENSE
88
+ Requires-Dist: pytest; extra == "devel"
89
+ Requires-Dist: pytest-cov; extra == "devel"
46
90
 
47
91
  # filesystem_spec
48
92
 
@@ -50,6 +94,7 @@ License-File: LICENSE
50
94
  [![Anaconda-Server Badge](https://anaconda.org/conda-forge/fsspec/badges/version.svg)](https://anaconda.org/conda-forge/fsspec)
51
95
  ![Build](https://github.com/fsspec/filesystem_spec/workflows/CI/badge.svg)
52
96
  [![Docs](https://readthedocs.org/projects/filesystem-spec/badge/?version=latest)](https://filesystem-spec.readthedocs.io/en/latest/?badge=latest)
97
+ [![PyPi downloads](https://img.shields.io/pypi/dm/fsspec?label=pypi%20downloads&style=flat)](https://pepy.tech/project/fsspec)
53
98
 
54
99
  A specification for pythonic filesystems.
55
100
 
@@ -4,6 +4,7 @@
4
4
  [![Anaconda-Server Badge](https://anaconda.org/conda-forge/fsspec/badges/version.svg)](https://anaconda.org/conda-forge/fsspec)
5
5
  ![Build](https://github.com/fsspec/filesystem_spec/workflows/CI/badge.svg)
6
6
  [![Docs](https://readthedocs.org/projects/filesystem-spec/badge/?version=latest)](https://filesystem-spec.readthedocs.io/en/latest/?badge=latest)
7
+ [![PyPi downloads](https://img.shields.io/pypi/dm/fsspec?label=pypi%20downloads&style=flat)](https://pepy.tech/project/fsspec)
7
8
 
8
9
  A specification for pythonic filesystems.
9
10
 
@@ -48,10 +48,15 @@ def process_entries():
48
48
  specs = eps.select(group="fsspec.specs")
49
49
  else:
50
50
  specs = eps.get("fsspec.specs", [])
51
+ registered_names = {}
51
52
  for spec in specs:
52
53
  err_msg = f"Unable to load filesystem from {spec}"
54
+ name = spec.name
55
+ if name in registered_names:
56
+ continue
57
+ registered_names[name] = True
53
58
  register_implementation(
54
- spec.name,
59
+ name,
55
60
  spec.value.replace(":", "."),
56
61
  errtxt=err_msg,
57
62
  # We take our implementations as the ones to overload with if
@@ -1,5 +1,5 @@
1
1
 
2
- # This file was generated by 'versioneer.py' (0.20) from
2
+ # This file was generated by 'versioneer.py' (0.29) from
3
3
  # revision-control system data, or from the parent directory name of an
4
4
  # unpacked source archive. Distribution tarballs contain a pre-generated copy
5
5
  # of this file.
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-09-22T14:30:26-0400",
11
+ "date": "2023-12-02T20:51:30-0500",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "3ad74814c8bd8620b3aa434080218eb658a81a6c",
15
- "version": "2023.9.2"
14
+ "full-revisionid": "5cf9cd952c5d276835d3caef9c32fcf69d55b10c",
15
+ "version": "2023.12.0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -13,7 +13,7 @@ class AbstractArchiveFileSystem(AbstractFileSystem):
13
13
  """
14
14
 
15
15
  def __str__(self):
16
- return "<Archive-like object %s at %s>" % (type(self).__name__, id(self))
16
+ return f"<Archive-like object {type(self).__name__} at {id(self)}>"
17
17
 
18
18
  __repr__ = __str__
19
19
 
@@ -15,7 +15,7 @@ from .callbacks import _DEFAULT_CALLBACK
15
15
  from .exceptions import FSTimeoutError
16
16
  from .implementations.local import LocalFileSystem, make_path_posix, trailing_sep
17
17
  from .spec import AbstractBufferedFile, AbstractFileSystem
18
- from .utils import is_exception, other_paths
18
+ from .utils import glob_translate, is_exception, other_paths
19
19
 
20
20
  private = re.compile("_[^_]")
21
21
  iothread = [None] # dedicated fsspec IO thread
@@ -106,7 +106,7 @@ def sync(loop, func, *args, timeout=None, **kwargs):
106
106
 
107
107
 
108
108
  def sync_wrapper(func, obj=None):
109
- """Given a function, make so can be called in async or blocking contexts
109
+ """Given a function, make so can be called in blocking contexts
110
110
 
111
111
  Leave obj=None if defining within a class. Pass the instance if attaching
112
112
  as an attribute of the instance.
@@ -426,7 +426,7 @@ class AsyncFileSystem(AbstractFileSystem):
426
426
  end = ""
427
427
  if isinstance(end, numbers.Integral):
428
428
  end -= 1 # bytes range is inclusive
429
- return "bytes=%s-%s" % (start, end)
429
+ return f"bytes={start}-{end}"
430
430
 
431
431
  async def _cat_file(self, path, start=None, end=None, **kwargs):
432
432
  raise NotImplementedError
@@ -467,6 +467,16 @@ class AsyncFileSystem(AbstractFileSystem):
467
467
  on_error="return",
468
468
  **kwargs,
469
469
  ):
470
+ """Get the contents of byte ranges from one or more files
471
+
472
+ Parameters
473
+ ----------
474
+ paths: list
475
+ A list of of filepaths on this filesystems
476
+ starts, ends: int or list
477
+ Bytes limits of the read. If using a single int, the same value will be
478
+ used to read all the specified files.
479
+ """
470
480
  # TODO: on_error
471
481
  if max_gap is not None:
472
482
  # use utils.merge_offset_ranges
@@ -476,7 +486,7 @@ class AsyncFileSystem(AbstractFileSystem):
476
486
  if not isinstance(starts, Iterable):
477
487
  starts = [starts] * len(paths)
478
488
  if not isinstance(ends, Iterable):
479
- ends = [starts] * len(paths)
489
+ ends = [ends] * len(paths)
480
490
  if len(starts) != len(paths) or len(ends) != len(paths):
481
491
  raise ValueError
482
492
  coros = [
@@ -662,9 +672,9 @@ class AsyncFileSystem(AbstractFileSystem):
662
672
  [self._size(p) for p in paths], batch_size=batch_size
663
673
  )
664
674
 
665
- async def _exists(self, path):
675
+ async def _exists(self, path, **kwargs):
666
676
  try:
667
- await self._info(path)
677
+ await self._info(path, **kwargs)
668
678
  return True
669
679
  except FileNotFoundError:
670
680
  return False
@@ -735,8 +745,12 @@ class AsyncFileSystem(AbstractFileSystem):
735
745
 
736
746
  import re
737
747
 
738
- ends = path.endswith("/")
748
+ seps = (os.path.sep, os.path.altsep) if os.path.altsep else (os.path.sep,)
749
+ ends_with_sep = path.endswith(seps) # _strip_protocol strips trailing slash
739
750
  path = self._strip_protocol(path)
751
+ append_slash_to_dirname = ends_with_sep or path.endswith(
752
+ tuple(sep + "**" for sep in seps)
753
+ )
740
754
  idx_star = path.find("*") if path.find("*") >= 0 else len(path)
741
755
  idx_qmark = path.find("?") if path.find("?") >= 0 else len(path)
742
756
  idx_brace = path.find("[") if path.find("[") >= 0 else len(path)
@@ -746,11 +760,11 @@ class AsyncFileSystem(AbstractFileSystem):
746
760
  detail = kwargs.pop("detail", False)
747
761
 
748
762
  if not has_magic(path):
749
- if await self._exists(path):
763
+ if await self._exists(path, **kwargs):
750
764
  if not detail:
751
765
  return [path]
752
766
  else:
753
- return {path: await self._info(path)}
767
+ return {path: await self._info(path, **kwargs)}
754
768
  else:
755
769
  if not detail:
756
770
  return [] # glob of non-existent returns empty
@@ -775,46 +789,22 @@ class AsyncFileSystem(AbstractFileSystem):
775
789
  allpaths = await self._find(
776
790
  root, maxdepth=depth, withdirs=True, detail=True, **kwargs
777
791
  )
778
- # Escape characters special to python regex, leaving our supported
779
- # special characters in place.
780
- # See https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html
781
- # for shell globbing details.
782
- pattern = (
783
- "^"
784
- + (
785
- path.replace("\\", r"\\")
786
- .replace(".", r"\.")
787
- .replace("+", r"\+")
788
- .replace("//", "/")
789
- .replace("(", r"\(")
790
- .replace(")", r"\)")
791
- .replace("|", r"\|")
792
- .replace("^", r"\^")
793
- .replace("$", r"\$")
794
- .replace("{", r"\{")
795
- .replace("}", r"\}")
796
- .rstrip("/")
797
- .replace("?", ".")
798
- )
799
- + "$"
800
- )
801
- pattern = re.sub("/[*]{2}", "=SLASH_DOUBLE_STARS=", pattern)
802
- pattern = re.sub("[*]{2}/?", "=DOUBLE_STARS=", pattern)
803
- pattern = re.sub("[*]", "[^/]*", pattern)
804
- pattern = re.sub("=SLASH_DOUBLE_STARS=", "(|/.*)", pattern)
805
- pattern = re.sub("=DOUBLE_STARS=", ".*", pattern)
792
+
793
+ pattern = glob_translate(path + ("/" if ends_with_sep else ""))
806
794
  pattern = re.compile(pattern)
795
+
807
796
  out = {
808
- p: allpaths[p]
809
- for p in sorted(allpaths)
810
- if pattern.match(p.replace("//", "/").rstrip("/"))
797
+ p: info
798
+ for p, info in sorted(allpaths.items())
799
+ if pattern.match(
800
+ (
801
+ p + "/"
802
+ if append_slash_to_dirname and info["type"] == "directory"
803
+ else p
804
+ )
805
+ )
811
806
  }
812
807
 
813
- # Return directories only when the glob end by a slash
814
- # This is needed for posix glob compliance
815
- if ends:
816
- out = {k: v for k, v in out.items() if v["type"] == "directory"}
817
-
818
808
  if detail:
819
809
  return out
820
810
  else: