data.py 1.6 KB

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