Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically modifying STAC objects using a custom StacIO #1371

Open
bmcandr opened this issue Jul 25, 2024 · 1 comment
Open

Automatically modifying STAC objects using a custom StacIO #1371

bmcandr opened this issue Jul 25, 2024 · 1 comment
Milestone

Comments

@bmcandr
Copy link
Contributor

bmcandr commented Jul 25, 2024

Following up from this discussion in the STAC Gitter. I created this issue for a discussion on the topic of ~automatically modifying STAC objects read with pystac a la pystac_client's support for automatically modifying results.


It is possible to define a custom StacIO class that overrides the StacIO.stac_object_from_dict method to pass the deserialized STAC object to a modifier function (e.g., planetary_computer.sign_inplace) before returning it:

from functools import wraps

import planetary_computer
import pystac
from pystac.stac_io import DefaultStacIO, StacIO

# Define custom StacIO that overrides stac_object_from_dict to pass StacObject to signing modifier
class PCStacIO(DefaultStacIO):
    @wraps(StacIO.stac_object_from_dict)
    def stac_object_from_dict(
        self,
        *args,
        **kwargs,
    ) -> pystac.STACObject:
        return planetary_computer.sign_inplace(
            super().stac_object_from_dict(*args, **kwargs)
        )


# Usage:

item_href = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/sentinel-2-l2a/items/S2B_MSIL2A_20240723T205029_R057_T16XDN_20240723T231445"

item = pystac.read_file(
    item_href,
    stac_io=PCStacIO(),  # pass instance of PCStacIO
)

# Asset HREFs have been signed
print(item.assets)

# Alternatively, set PCStacIO as default StacIO
StacIO.set_default(PCStacIO)

item = pystac.read_file(item_href)

print(item.assets)

When I wrote the custom StacIO class I naively expected that the pystac.Item.from_file would use the StacIO.stac_object_from_dict method, but that is not the case. Invoking the modifier requires reading the STAC objects with the pystac.read_file method. This is because the pystac.STACObject.from_file methods do not rely on StacIO.stac_object_from_dict (in fact the latter relies on the former).

Thinking "out loud" about how to enable the pystac.STACObject.from_file... add a _modifier class variable that is a Callable[[Modifiable], STACObject] and have the STACObject.from_file methods optionally apply the _modifier if it is set? I don't love it...

That said, it's not clear whether there is any demand for enabling this functionality when using the pystac.read_file or separately and explicitly passing STAC objects to a modifier function approaches work just as well. Using the from_file approach would appease mypy w/o the need for casting, but that's a pretty minor DevX nit tbh. Maybe this example is informative enough for the docs?

All feedback is welcome.

@gadomski
Copy link
Member

separately and explicitly passing STAC objects to a modifier function approaches work just as well.

As things currently exist, this is my instinct. For a (currently hypothetical) PySTAC v2, it's likely that the whole StacIO mechanism will get a significant refactor (see #675, #506), and auto-magically transforming objects (e.g. by signing assets) could be a good feature to include. I'd like to keep this issue open to track that need 👍🏼.

@gadomski gadomski added this to the 2.0 milestone Jul 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants