data.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import base64
  2. import io
  3. from urllib.parse import unquote
  4. from fsspec import AbstractFileSystem
  5. class DataFileSystem(AbstractFileSystem):
  6. """A handy decoder for data-URLs
  7. Example
  8. -------
  9. >>> with fsspec.open("data:,Hello%2C%20World%21") as f:
  10. ... print(f.read())
  11. b"Hello, World!"
  12. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
  13. """
  14. protocol = "data"
  15. def __init__(self, **kwargs):
  16. """No parameters for this filesystem"""
  17. super().__init__(**kwargs)
  18. def cat_file(self, path, start=None, end=None, **kwargs):
  19. pref, data = path.split(",", 1)
  20. if pref.endswith("base64"):
  21. return base64.b64decode(data)[start:end]
  22. return unquote(data).encode()[start:end]
  23. def info(self, path, **kwargs):
  24. pref, name = path.split(",", 1)
  25. data = self.cat_file(path)
  26. mime = pref.split(":", 1)[1].split(";", 1)[0]
  27. return {"name": name, "size": len(data), "type": "file", "mimetype": mime}
  28. def _open(
  29. self,
  30. path,
  31. mode="rb",
  32. block_size=None,
  33. autocommit=True,
  34. cache_options=None,
  35. **kwargs,
  36. ):
  37. if "r" not in mode:
  38. raise ValueError("Read only filesystem")
  39. return io.BytesIO(self.cat_file(path))
  40. @staticmethod
  41. def encode(data: bytes, mime: str | None = None):
  42. """Format the given data into data-URL syntax
  43. This version always base64 encodes, even when the data is ascii/url-safe.
  44. """
  45. return f"data:{mime or ''};base64,{base64.b64encode(data).decode()}"