Skip to content

Commit 1800edd

Browse files
authored
refactor!: remove the typed dicts (#177)
They don't really belong here.
1 parent 3754c0c commit 1800edd

File tree

5 files changed

+20
-261
lines changed

5 files changed

+20
-261
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55

66
## [Unreleased]
77

8+
### Removed
9+
10+
- STAC typed dicts ([#177](https://github.com/stac-utils/rustac-py/pull/177))
11+
812
## [0.8.4] - 2025-10-22
913

1014
### Fixed

python/rustac/__init__.py

Lines changed: 1 addition & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -1,258 +1,12 @@
11
from __future__ import annotations
22

33
from .rustac import *
4-
from typing import TypedDict, Required, Any, Literal
54
from . import store
65

7-
8-
class Catalog(TypedDict, total=False):
9-
"""A STAC Catalog object represents a logical group of other Catalog, Collection, and Item objects."""
10-
11-
type: Required[str]
12-
"""Set to Catalog if this Catalog only implements the Catalog spec."""
13-
14-
stac_version: Required[str]
15-
"""The STAC version the Catalog implements."""
16-
17-
stac_extensions: list[str] | None
18-
"""A list of extension identifiers the Catalog implements."""
19-
20-
id: Required[str]
21-
"""Identifier for the Catalog."""
22-
23-
title: str | None
24-
"""A short descriptive one-line title for the Catalog."""
25-
26-
description: Required[str]
27-
"""Detailed multi-line description to fully explain the Catalog.
28-
29-
CommonMark 0.29 syntax MAY be used for rich text representation."""
30-
31-
links: Required[list[Link]]
32-
"""A list of references to other documents."""
33-
34-
class Collection(TypedDict, total=False):
35-
"""The STAC Collection Specification defines a set of common fields to describe a group of Items that share properties and metadata."""
36-
37-
type: Required[str]
38-
"""Must be set to Collection to be a valid Collection."""
39-
40-
stac_version: Required[str]
41-
"""The STAC version the Collection implements."""
42-
43-
stac_extensions: list[str] | None
44-
"""A list of extension identifiers the Collection implements."""
45-
46-
id: Required[str]
47-
"""Identifier for the Collection that is unique across all collections in the root catalog."""
48-
49-
title: str | None
50-
"""A short descriptive one-line title for the Collection."""
51-
52-
description: Required[str]
53-
"""Detailed multi-line description to fully explain the Collection.
54-
55-
CommonMark 0.29 syntax MAY be used for rich text representation."""
56-
57-
keywords: list[str] | None
58-
"""List of keywords describing the Collection."""
59-
60-
license: Required[str]
61-
"""License(s) of the data collection as SPDX License identifier, SPDX License expression, or `other`."""
62-
63-
providers: list[Provider] | None
64-
"""A list of providers, which may include all organizations capturing or processing the data or the hosting provider."""
65-
66-
extent: Required[Extent]
67-
"""Spatial and temporal extents."""
68-
69-
summaries: dict[str, Any] | None
70-
"""A map of property summaries, either a set of values, a range of values or a JSON Schema."""
71-
72-
links: Required[list[Link]]
73-
"""A list of references to other documents."""
74-
75-
assets: dict[str, Asset] | None
76-
"""Dictionary of asset objects that can be downloaded, each with a unique key."""
77-
78-
item_assets: dict[str, ItemAsset] | None
79-
"""A dictionary of assets that can be found in member Items."""
80-
81-
class Provider(TypedDict, total=False):
82-
"""A provider is any of the organizations that captures or processes the content of the Collection and therefore influences the data offered by this Collection."""
83-
84-
name: Required[str]
85-
"""The name of the organization or the individual."""
86-
87-
description: str | None
88-
"""Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information.
89-
90-
CommonMark 0.29 syntax MAY be used for rich text representation."""
91-
92-
roles: list[
93-
Literal["licensor"]
94-
| Literal["producer"]
95-
| Literal["processor"]
96-
| Literal["host"]
97-
] | None
98-
"""Roles of the provider."""
99-
100-
url: str | None
101-
"""Homepage on which the provider describes the dataset and publishes contact information."""
102-
103-
class Extent(TypedDict):
104-
"""The object describes the spatio-temporal extents of the Collection."""
105-
106-
spatial: SpatialExtent
107-
"""Potential spatial extents covered by the Collection."""
108-
109-
temporal: TemporalExtent
110-
"""Potential temporal extents covered by the Collection."""
111-
112-
class SpatialExtent(TypedDict):
113-
"""The object describes the spatial extents of the Collection."""
114-
115-
bbox: list[list[int | float]]
116-
"""Potential spatial extents covered by the Collection."""
117-
118-
class TemporalExtent(TypedDict):
119-
"""The object describes the temporal extents of the Collection."""
120-
121-
bbox: list[list[str | None]]
122-
"""Potential temporal extents covered by the Collection."""
123-
124-
class ItemAsset(TypedDict, total=False):
125-
"""An Item Asset Object defined at the Collection level is nearly the same as the Asset Object in Items, except for two differences.
126-
127-
The href field is not required, because Item Asset Definitions don't point to any data by themselves, but at least two other fields must be present."""
128-
129-
title: str | None
130-
"""The displayed title for clients and users."""
131-
132-
description: str | None
133-
"""A description of the Asset providing additional details, such as how it was processed or created.
134-
135-
CommonMark 0.29 syntax MAY be used for rich text representation."""
136-
137-
type: str | None
138-
"""Media type of the asset."""
139-
140-
roles: list[str] | None
141-
"""The semantic roles of the asset, similar to the use of rel in links."""
142-
143-
class Item(TypedDict, total=False):
144-
"""An Item is a GeoJSON Feature augmented with foreign members relevant to a STAC object."""
145-
146-
type: Required[str]
147-
"""Type of the GeoJSON Object. MUST be set to Feature."""
148-
149-
stac_version: Required[str]
150-
"""The STAC version the Item implements."""
151-
152-
stac_extensions: list[str] | None
153-
"""A list of extensions the Item implements."""
154-
155-
id: Required[str]
156-
"""Provider identifier. The ID should be unique within the Collection that contains the Item."""
157-
158-
geometry: dict[str, Any] | None
159-
"""Defines the full footprint of the asset represented by this item, formatted according to RFC 7946, section 3.1 if a geometry is provided or section 3.2 if no geometry is provided."""
160-
161-
bbox: list[int | float] | None
162-
"""REQUIRED if geometry is not null, prohibited if geometry is null.
163-
164-
Bounding Box of the asset represented by this Item, formatted according to RFC 7946, section 5."""
165-
166-
properties: Required[Properties]
167-
"""A dictionary of additional metadata for the Item."""
168-
169-
links: Required[list[Link]]
170-
"""List of link objects to resources and related URLs.
171-
172-
See the best practices for details on when the use self links is strongly recommended."""
173-
174-
assets: Required[dict[str, Asset]]
175-
"""Dictionary of asset objects that can be downloaded, each with a unique key."""
176-
177-
collection: str | None
178-
"""The id of the STAC Collection this Item references to.
179-
180-
This field is required if a link with a collection relation type is present and is not allowed otherwise."""
181-
182-
class Properties(TypedDict):
183-
"""Additional metadata fields can be added to the GeoJSON Object Properties."""
184-
185-
datetime: str | None
186-
"""The searchable date and time of the assets, which must be in UTC.
187-
188-
It is formatted according to RFC 3339, section 5.6. null is allowed, but requires start_datetime and end_datetime from common metadata to be set."""
189-
190-
class Link(TypedDict, total=False):
191-
"""This object describes a relationship with another entity.
192-
193-
Data providers are advised to be liberal with the links section, to describe
194-
things like the Catalog an Item is in, related Items, parent or child Items
195-
(modeled in different ways, like an 'acquisition' or derived data)."""
196-
197-
href: Required[str]
198-
"""The actual link in the format of an URL.
199-
200-
Relative and absolute links are both allowed. Trailing slashes are significant."""
201-
202-
rel: Required[str]
203-
"""Relationship between the current document and the linked document."""
204-
205-
type: str | None
206-
"""Media type of the referenced entity."""
207-
208-
title: str | None
209-
"""A human readable title to be used in rendered displays of the link."""
210-
211-
method: str | None
212-
"""The HTTP method that shall be used for the request to the target resource, in uppercase.
213-
214-
GET by default"""
215-
216-
headers: dict[str, str | list[str]] | None
217-
"""The HTTP headers to be sent for the request to the target resource."""
218-
219-
body: Any | None
220-
"""The HTTP body to be sent to the target resource."""
221-
222-
class Asset(TypedDict, total=False):
223-
"""An Asset is an object that contains a URI to data associated with the Item that can be downloaded or streamed.
224-
225-
It is allowed to add additional fields."""
226-
227-
href: Required[str]
228-
"""URI to the asset object. Relative and absolute URI are both allowed. Trailing slashes are significant."""
229-
230-
title: str | None
231-
"""The displayed title for clients and users."""
232-
233-
description: str | None
234-
"""A description of the Asset providing additional details, such as how it was processed or created.
235-
236-
CommonMark 0.29 syntax MAY be used for rich text representation."""
237-
238-
type: str | None
239-
"""Media type of the asset.
240-
241-
See the common media types in the best practice doc for commonly used asset types."""
242-
243-
roles: list[str] | None
244-
"""The semantic roles of the asset, similar to the use of rel in links."""
245-
246-
class ItemCollection(TypedDict):
247-
"""A GeoJSON feature collection of STAC Items."""
248-
249-
features: list[Item]
250-
"""STAC items."""
251-
2526
__doc__ = rustac.__doc__
2537
if hasattr(rustac, "__all__"):
2548
__all__ = rustac.__all__
2559
else:
25610
__all__ = []
25711

258-
__all__.append("store")
12+
__all__.append("store")

python/rustac/rustac.pyi

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ from typing import Any, Literal
77
import arro3.core
88
from obstore.store import ObjectStore as ObstoreObjectStore
99

10-
from rustac import Catalog, Collection, Item, ItemCollection
1110
from rustac.store import ObjectStore
1211

1312
AnyObjectStore = ObjectStore | ObstoreObjectStore
@@ -154,7 +153,7 @@ class DuckdbClient:
154153
>>> data_frame = GeoDataFrame.from_arrow(table)
155154
"""
156155

157-
def get_collections(self, href: str) -> list[Collection]:
156+
def get_collections(self, href: str) -> list[dict[str, Any]]:
158157
"""Returns all collections in this stac-geoparquet file.
159158
160159
These collections will be auto-generated from the STAC items, one
@@ -170,7 +169,9 @@ class DuckdbClient:
170169
A list of STAC Collections
171170
"""
172171

173-
def collection_from_id_and_items(id: str, items: list[Item]) -> Collection:
172+
def collection_from_id_and_items(
173+
id: str, items: list[dict[str, Any]]
174+
) -> dict[str, Any]:
174175
"""Creates a collection from an id and some items.
175176
176177
The extents will be calculated from the items, and the items will be linked.
@@ -237,7 +238,7 @@ async def read(
237238

238239
def from_arrow(
239240
table: arro3.core.Table,
240-
) -> ItemCollection:
241+
) -> dict[str, Any]:
241242
"""
242243
Converts an [arro3.core.Table][] to a STAC item collection.
243244
@@ -251,7 +252,7 @@ def from_arrow(
251252
"""
252253

253254
def to_arrow(
254-
items: list[Item] | ItemCollection,
255+
items: list[dict[str, Any]] | dict[str, Any],
255256
) -> arro3.core.Table:
256257
"""
257258
Converts items to an [arro3.core.Table][].
@@ -478,7 +479,7 @@ async def search_to(
478479

479480
def walk(
480481
container: dict[str, Any],
481-
) -> AsyncIterator[tuple[Catalog | Collection, list[Catalog | Collection], list[Item]]]:
482+
) -> AsyncIterator[tuple[dict[str, Any], list[dict[str, Any]], list[dict[str, Any]]]]:
482483
"""Recursively walks a STAC catalog or collection breadth-first.
483484
484485
Args:

tests/conftest.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import json
22
from pathlib import Path
3-
from typing import cast
3+
from typing import Any
44

55
import pystac
66
import pytest
7-
from rustac import Item
87

98

109
@pytest.fixture
@@ -28,18 +27,18 @@ def data(root: Path) -> Path:
2827

2928

3029
@pytest.fixture
31-
def item(examples: Path) -> Item:
30+
def item(examples: Path) -> dict[str, Any]:
3231
with open(examples / "simple-item.json") as f:
3332
return json.load(f)
3433

3534

3635
@pytest.fixture
37-
def maxar_items(root: Path) -> list[Item]:
36+
def maxar_items(root: Path) -> list[dict[str, Any]]:
3837
# https://github.com/stac-utils/rustac/issues/722
3938
directory = root / "tests" / "data" / "maxar-hurricane-ian-2022"
4039
item_a = pystac.read_file(directory / "031331303020" / "10300100DB064000.json")
4140
item_b = pystac.read_file(directory / "031331303211" / "10300100DB064000.json")
4241
return [
43-
cast(Item, item_a.to_dict(transform_hrefs=False)),
44-
cast(Item, item_b.to_dict(transform_hrefs=False)),
42+
item_a.to_dict(transform_hrefs=False),
43+
item_b.to_dict(transform_hrefs=False),
4544
]

tests/test_arrow.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
from typing import Any
2+
13
import pytest
24
import rustac
35
from geopandas import GeoDataFrame
4-
from rustac import Item
56

67
pytest.importorskip("arro3.core")
78

89

9-
def test_to_arrow(item: Item) -> None:
10+
def test_to_arrow(item: dict[str, Any]) -> None:
1011
table = rustac.to_arrow([item])
1112
data_frame = GeoDataFrame.from_arrow(table)
1213
assert len(data_frame) == 1

0 commit comments

Comments
 (0)