Skip to content

feat!: pystac v2#1524

Draft
gadomski wants to merge 57 commits intomainfrom
v2
Draft

feat!: pystac v2#1524
gadomski wants to merge 57 commits intomainfrom
v2

Conversation

@gadomski
Copy link
Member

@gadomski gadomski commented Feb 13, 2025

PySTAC v2.0 is a ground-up re-write of PySTAC. Our high-level design goals are a form of Postel's law:

  • Help people make the best STAC possible
  • Help people interact with existing (even poorly constructed or invalid) STAC as easily as possible

To do so, we have some specific implementation strategies.

  • Keep the core data structure APIs basically the same: People are used to the basic methods on Item, Catalog, Collection, etc. We shouldn't change the external APIs unless there's a good reason to.
  • Relax core data structure initializers to accept almost anything, with warnings if something's being changed to make it valid
  • Stay low-dependency by default: This keeps our maintenance burden lower, at the cost of having to hand-roll more stuff ourselves.
  • Replace "implementation" APIs: Item, Catalog, etc are the "what" of pystac. Things like StacIO are the "how". We should create replacement structures for any of these "how" interfaces that we want to dramatically change, rather than try to "fix" the existing ones. Backwards compatibility will be much more difficult for these "how" interfaces, so we shouldn't even try. If possible we should re-write the existing "how" structure (e.g. StacIO) to use the new API, but this should be a lower-priority objective.
  • Do fewer things at once: One of the biggest design problems of PySTAC v1.0 (in this author's opinion) was that many functions tried to be "helpful" by doing a lot of things at once. When possible, we should simplify methods to do just one thing, and provide intuitive patterns for doing complex operations using multiple method calls. Top-level functions can be used to "synthesize" complex operations, e.g. pystac.read_file.

We've got v2 docs here: https://stac-utils.github.io/pystac/

v1 test compatibility

To break the API as little as possible, we're keeping the v1 test suite in tests/v1. As we build v2, we'll update this table to show how close we are to passing all1 v1 tests:

Status Count
❌ Failed 687
✅ Passing 871
✅ Xfailed 14
⚠️ Warnings 1761
❌ Errors 17

Footnotes

  1. Some tests, such as those that check for exceptions that we've relaxed, we mark as xfail

@gadomski gadomski changed the title feat: pystac v2 feat!: pystac v2 Jan 7, 2026
@gadomski gadomski marked this pull request as ready for review January 8, 2026 03:57
* Adds skip to all the v1 tests by default
* Unskip v1 tests or files using `passing_v2` marker
@jsignell
Copy link
Member

There is a new pytest marker that you can add to a v1 file or specific test to "turn it on" for this branch. I turned on tests/v1/test_item.py even though one of those tests is failing to prove that it works:

Output
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
rootdir: /home/runner/work/pystac/pystac
configfile: pyproject.toml
plugins: requests-mock-1.12.1, mock-3.15.1, recording-0.13.4
collected 1613 items / 1 skipped

tests/test_catalog.py sss                                                [  0%]
tests/test_collection.py sss                                             [  0%]
tests/test_examples.py ssssssssssssssssssssssssssssssssssssssss          [  2%]
tests/test_item.py sssss                                                 [  3%]
tests/v1/extensions/test_classification.py ssssssssssssssssssss          [  4%]
tests/v1/extensions/test_custom.py sssssss                               [  4%]
tests/v1/extensions/test_datacube.py sssssssssssssssssssssssssssssssss   [  6%]
tests/v1/extensions/test_eo.py sssssssssssssssssssssssssssssssssssssssss [  9%]
s                                                                        [  9%]
tests/v1/extensions/test_ext.py ssssssssssssssssssssssssssssssssssssssss [ 11%]
ssssssssssss                                                             [ 12%]
tests/v1/extensions/test_file.py sssssssssssssssssssssssssssssssss       [ 14%]
tests/v1/extensions/test_grid.py ssssssssssss                            [ 15%]
tests/v1/extensions/test_mgrs.py sssssssssssssssssss                     [ 16%]
tests/v1/extensions/test_mlm.py ssssssssssssssssssssssssssssssssssssssss [ 19%]
ssssss                                                                   [ 19%]
tests/v1/extensions/test_pointcloud.py ssssssssssssssssssssss            [ 20%]
tests/v1/extensions/test_projection.py sssssssssssssssssssssssssssssssss [ 22%]
ss                                                                       [ 23%]
tests/v1/extensions/test_raster.py sssssssss                             [ 23%]
tests/v1/extensions/test_render.py ssssssssssssssssss                    [ 24%]
tests/v1/extensions/test_sar.py ssssssssssssssssssssss                   [ 26%]
tests/v1/extensions/test_sat.py ssssssssssssssssssssssssss               [ 27%]
tests/v1/extensions/test_scientific.py sssssssssssssssssssssssssssssssss [ 29%]
ssss                                                                     [ 30%]
tests/v1/extensions/test_storage.py sssssssssssssssssssssss              [ 31%]
tests/v1/extensions/test_table.py sssssssss                              [ 31%]
tests/v1/extensions/test_timestamps.py sssssssssssssssss                 [ 33%]
tests/v1/extensions/test_version.py ssssssssssssssssssssssssssssss       [ 34%]
tests/v1/extensions/test_view.py sssssssssssssssssssssss                 [ 36%]
tests/v1/extensions/test_xarray_assets.py sssssssssssssssssssss          [ 37%]
tests/v1/html/test_html.py ssssssssss                                    [ 38%]
tests/v1/posix_paths/test_posix_paths.py ssssssss                        [ 38%]
tests/v1/serialization/test_identify.py ssssssssssssssssssssssssssssssss [ 40%]
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss [ 45%]
sssssssssssssssssssssssssssss                                            [ 46%]
tests/v1/serialization/test_migrate.py sssssssssssssssssssssssssssssssss [ 49%]
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss [ 53%]
ssssssssssssssssssssssssssss                                             [ 55%]
tests/v1/test_asset.py sssssssssssssssssss                               [ 56%]
tests/v1/test_cache.py ssss                                              [ 56%]
tests/v1/test_catalog.py sssssssssssssssssssssssssssssssssssssssssssssss [ 59%]
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss [ 64%]
ssssssssssssssssssssss                                                   [ 65%]
tests/v1/test_collection.py ssssssssssssssssssssssssssssssssssssssssssss [ 68%]
sssssssss                                                                [ 68%]
tests/v1/test_common_metadata.py ssssssssssssssssssssss                  [ 70%]
tests/v1/test_item.py ..........x.x...............xxx............x...... [ 73%]
.F.                                                                      [ 73%]
tests/v1/test_item_assets.py sssssssssssss                               [ 74%]
tests/v1/test_item_collection.py ssssssssssssssssss                      [ 75%]
tests/v1/test_layout.py sssssssssssssssssssssssssssssssssssssssssssss    [ 78%]
tests/v1/test_link.py ssssssssssssssssssssssssssssssssssssssssss         [ 80%]
tests/v1/test_pystac_client.py ss                                        [ 80%]
tests/v1/test_stac_io.py ssssssssssssssss                                [ 81%]
tests/v1/test_summaries.py sssssssssss                                   [ 82%]
tests/v1/test_utils.py sssssssssssssssssssssssssssssssssssssssssssssssss [ 85%]
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss       [ 89%]
tests/v1/test_version.py ss                                              [ 89%]
tests/v1/test_writing.py sssssssssssssssssssss                           [ 91%]
tests/v1/validation/test_schema_uri_map.py s                             [ 91%]
tests/v1/validation/test_validate.py sssssssssssssssssssssssssssssssssss [ 93%]
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss [ 97%]
sssssssssssssssssssssssssssssssssssss                                    [100%]

=================================== FAILURES ===================================
___________________________ test_migrate_by_default ____________________________

    def test_migrate_by_default() -> None:
        with open(
            TestCases.get_path("data-files/projection/example-with-version-1.1.json")
        ) as f:
            data = json.load(f)
        item = pystac.Item.from_dict(data)  # default used to be migrate=False
>       assert item.ext.proj.code == "EPSG:32614"
               ^^^^^^^^
E       AttributeError: 'Item' object has no attribute 'ext'

tests/v1/test_item.py:697: AttributeError
=========================== short test summary info ============================
FAILED tests/v1/test_item.py::test_migrate_by_default - AttributeError: 'Item' object has no attribute 'ext'
============ 1 failed, 46 passed, 1561 skipped, 6 xfailed in 3.43s =============

@jsignell
Copy link
Member

☝🏻 8d615c2 should be green

@jsignell
Copy link
Member

Ok! I am skipping check-benchmarks, coverage, docs, and without-json. Looks like there is still something going wrong with windows...

* If the file exists, read it
* Just write it if it's windows and not obvioiusly a url
* Use the DEFAULT_READER even in the validator
@jsignell
Copy link
Member

I think the windows tests will pass now and we'll be all green

* Add bands as a top-level constuct
* Add repr for bands
* New implementation of CommonMetadata
* Add common metadata protocols to Item and Asset
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

Successfully merging this pull request may close these issues.

2 participants