Skip to content

Commit a0e884f

Browse files
committed
feat: add typed dicts
1 parent 91865b0 commit a0e884f

File tree

3 files changed

+265
-8
lines changed

3 files changed

+265
-8
lines changed

docs/api/stac.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# STAC
2+
3+
Typed dictionaries for STAC entities.
4+
5+
::: rustac.Catalog
6+
::: rustac.Collection
7+
::: rustac.Item
8+
::: rustac.ItemCollection

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ nav:
2525
- migrate: api/migrate.md
2626
- read: api/read.md
2727
- search: api/search.md
28+
- stac: api/stac.md
2829
- version: api/version.md
2930
- walk: api/walk.md
3031
- write: api/write.md

rustac.pyi

Lines changed: 256 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,255 @@
1-
from typing import Any, AsyncIterator, Literal, Optional, Tuple
1+
"""The power of Rust for the Python STAC ecosystem."""
2+
3+
from __future__ import annotations
4+
5+
from typing import Any, AsyncIterator, Literal, Optional, Tuple, TypedDict
26

37
import arro3.core
48

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

@@ -144,7 +392,7 @@ class DuckdbClient:
144392
>>> data_frame = GeoDataFrame.from_arrow(table)
145393
"""
146394

147-
def get_collections(self, href: str) -> list[dict[str, Any]]:
395+
def get_collections(self, href: str) -> list[Collection]:
148396
"""Returns all collections in this stac-geoparquet file.
149397
150398
These collections will be auto-generated from the STAC items, one
@@ -215,7 +463,7 @@ async def read(
215463

216464
def from_arrow(
217465
table: arro3.core.Table,
218-
) -> dict[str, Any]:
466+
) -> ItemCollection:
219467
"""
220468
Converts an [arro3.core.Table][] to a STAC item collection.
221469
@@ -229,7 +477,7 @@ def from_arrow(
229477
"""
230478

231479
def to_arrow(
232-
items: list[dict[str, Any]] | dict[str, Any],
480+
items: list[Item] | ItemCollection,
233481
) -> arro3.core.Table:
234482
"""
235483
Converts items to an [arro3.core.Table][].
@@ -260,7 +508,7 @@ async def search(
260508
query: Optional[dict[str, Any]] = None,
261509
use_duckdb: Optional[bool] = None,
262510
**kwargs: str,
263-
) -> list[dict[str, Any]]:
511+
) -> dict[str, Any]:
264512
"""
265513
Searches a STAC API server.
266514
@@ -299,10 +547,10 @@ async def search(
299547
kwargs: Additional parameters to pass in to the search.
300548
301549
Returns:
302-
A list of the returned STAC items.
550+
A feature collection of the returned STAC items.
303551
304552
Examples:
305-
>>> items = await rustac.search(
553+
>>> item_collection = await rustac.search(
306554
... "https://landsatlook.usgs.gov/stac-server",
307555
... collections=["landsat-c2l2-sr"],
308556
... intersects={"type": "Point", "coordinates": [-105.119, 40.173]},
@@ -387,7 +635,7 @@ async def search_to(
387635

388636
def walk(
389637
container: dict[str, Any],
390-
) -> AsyncIterator[tuple[dict[str, Any], list[dict[str, Any]], list[dict[str, Any]]]]:
638+
) -> AsyncIterator[tuple[Catalog | Collection, list[Catalog | Collection], list[Item]]]:
391639
"""Recursively walks a STAC catalog or collection breadth-first.
392640
393641
Args:

0 commit comments

Comments
 (0)