Source code for stactools.core.io

"""Input/output utility functions and definitions."""

import os
from typing import Any, Callable, Optional

import fsspec
from pystac.link import HREF
from pystac.stac_io import StacIO
from stactools.core import utils

ReadHrefModifier = Callable[[str], str]
"""Type alias for a function parameter that allows users to manipulate HREFs.

Used for reading, e.g. appending an Azure SAS Token or translating to a
signed URL.
"""


[docs] def read_text( href: str, read_href_modifier: Optional[ReadHrefModifier] = None, **kwargs: Any, ) -> str: """Reads a string from an href. If ``read_href_modifier`` is provided, then ``href`` will be passed through this function before use. This function uses the default :py:class:`pystac.StacIO`. Args: href (str): The href to be read read_href_modifier (ReadHrefModifier, optional): A function to modify the provided href. Defaults to None. **kwargs : Arbitrary keyword arguments that may be utilized by the concrete implementation. Returns: str: The text as read from the href. """ if read_href_modifier is None: return StacIO.default().read_text(href, **kwargs) else: return StacIO.default().read_text(read_href_modifier(href), **kwargs)
[docs] class FsspecStacIO(StacIO): """A subclass of :py:class:`pystac.DefaultStacIO` that uses `fsspec <https://filesystem-spec.readthedocs.io/en/latest/>`_ for reads and writes."""
[docs] def read_text(self, source: HREF, *args: Any, **kwargs: Any) -> str: """A concrete implementation of :meth:`StacIO.read_text <pystac.StacIO.read_text>`. Converts the ``source`` argument to a string (if it is not already) and delegates to :meth:`FsspecStacIO.read_text_from_href` for opening and reading the file. """ href = str(os.fspath(source)) return self.read_text_from_href(href, **kwargs)
[docs] def read_text_from_href(self, href: str, **kwargs: Any) -> str: """Reads a file as a utf-8 string using `fsspec <https://filesystem-spec.readthedocs.io/en/latest/>`_. Args: href (str): The href to read. **kwargs: Additional keyword arguments to be passed to fsspec.open. Returns: str: The read text, decoded as utf-8 if necessary. """ with fsspec.open(href, "r", **kwargs) as f: s = f.read() if isinstance(s, str): return s elif isinstance(s, bytes): return str(s, encoding="utf-8") else: raise ValueError(f"Unable to decode data loaded from HREF: {href}")
[docs] def write_text(self, dest: HREF, txt: str, *args: Any, **kwargs: Any) -> None: """A concrete implementation of :meth:`StacIO.write_text <pystac.StacIO.write_text>`. Converts the ``dest`` argument to a string (if it is not already) and delegates to :meth:`FsspecStacIO.write_text_from_href` for opening and reading the file. """ # noqa: E501 href = str(os.fspath(dest)) return self.write_text_to_href(href, txt, **kwargs)
def write_text_from_href(self, href: str, txt: str) -> None: utils.deprecate( "FsspecStacIO.write_text_from_href", "FsspecStacIO.write_text_to_href", "v0.5.0", ) return self.write_text_to_href(href, txt)
[docs] def write_text_to_href(self, href: str, txt: str, **kwargs: Any) -> None: """Writes text to an href using fsspec. Args: href (str): The href to write to. txt (str): The text to write. **kwargs: Additional keyword arguments to be passed to fsspec.open. """ with fsspec.open(href, "w", auto_mkdir=True, **kwargs) as destination: destination.write(txt)
[docs] def use_fsspec() -> None: """Sets the default :py:class:`pystac.StacIO` to :py:class:`FsspecStacIO`.""" StacIO.set_default(FsspecStacIO)