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

Update to STAC spec 1.0.0 #86

Merged
merged 14 commits into from
Jun 25, 2021
7 changes: 6 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
1.3.9 (2020-03-02)
Unreleased
------------------
- Update to stac version 1.0.0 (#86, @moradology)
- Remove models for STAC spec extensions (#86, @moradology)

1.3.9 (2021-03-02)
------------------
- Add id to landing page, making it a valid catalog (#43, @lossyrob)
- Make `item_assets` (item assets extension) a dictionary of assets (#47, @kylebarron)
Expand Down
12 changes: 10 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
desc = f.read()

extras = {
"dev": ["arrow", "pytest", "pytest-cov", "requests", "shapely", "dictdiffer"],
"dev": [
"arrow",
"pytest",
"pytest-cov",
"requests",
"shapely",
"dictdiffer",
"jsonschema",
],
}

setup(
Expand All @@ -30,7 +38,7 @@
license="MIT",
packages=find_packages(exclude=["tests"]),
zip_safe=False,
install_requires=["click", "pydantic>=1.6", "geojson-pydantic",],
install_requires=["click", "pydantic>=1.6", "geojson-pydantic"],
tests_require=extras["dev"],
setup_requires=["pytest-runner"],
entry_points={"console_scripts": ["stac-pydantic=stac_pydantic.scripts.cli:app"]},
Expand Down
9 changes: 1 addition & 8 deletions stac_pydantic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
from .catalog import Catalog
from .collection import Collection
from .extensions import Extensions
from .item import (
Item,
ItemCollection,
ItemProperties,
item_model_factory,
validate_item,
)
from .item import Item, ItemCollection, ItemProperties
4 changes: 2 additions & 2 deletions stac_pydantic/api/extensions/sort.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from enum import auto

from pydantic import BaseModel
from pydantic import BaseModel, constr

from stac_pydantic.utils import AutoValueEnum

Expand All @@ -15,5 +15,5 @@ class SortExtension(BaseModel):
https://github.com/radiantearth/stac-api-spec/tree/master/extensions/sort#sort-api-extension
"""

field: str
field: constr(min_length=1)
direction: SortDirections
9 changes: 4 additions & 5 deletions stac_pydantic/api/landing.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from typing import List, Optional, Union

from pydantic import BaseModel, Field
from pydantic import AnyUrl, BaseModel, Field, constr

from stac_pydantic.links import Links
from stac_pydantic.shared import ExtensionTypes
from stac_pydantic.version import STAC_VERSION


Expand All @@ -12,9 +11,9 @@ class LandingPage(BaseModel):
https://github.com/radiantearth/stac-api-spec/blob/master/api-spec.md#ogc-api---features-endpoints
"""

id: str
description: str
id: constr(min_length=1)
description: constr(min_length=1)
title: Optional[str]
stac_version: str = Field(STAC_VERSION, const=True)
stac_extensions: Optional[List[Union[str, ExtensionTypes]]]
stac_extensions: Optional[List[AnyUrl]]
links: Links
2 changes: 1 addition & 1 deletion stac_pydantic/api/utils/link_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class BaseLinks:
"""Create inferred links common to collections and items."""

base_url: str
_link_members: ClassVar[Tuple[str]] = ("root")
_link_members: ClassVar[Tuple[str]] = ("root",)

def root(self) -> Link:
"""Return the catalog root."""
Expand Down
25 changes: 8 additions & 17 deletions stac_pydantic/catalog.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,28 @@
from typing import List, Optional

from pydantic import BaseModel, Field, root_validator
from pydantic import AnyUrl, BaseModel, Field, constr, root_validator

from stac_pydantic.extensions import Extensions
from stac_pydantic.links import Link, Links
from stac_pydantic.links import Links
from stac_pydantic.version import STAC_VERSION


class Catalog(BaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/catalog-spec/catalog-spec.md
https://github.com/radiantearth/stac-spec/blob/v1.0.0/catalog-spec/catalog-spec.md
"""

id: str
description: str
stac_version: str = Field(STAC_VERSION, const=True)
id: constr(min_length=1)
description: constr(min_length=1)
stac_version: constr(min_length=1) = Field(STAC_VERSION, const=True)
links: Links
stac_extensions: Optional[List[str]]
stac_extensions: Optional[List[AnyUrl]]
title: Optional[str]
type: constr(min_length=1) = Field("catalog", const=True)

class Config:
use_enum_values = True
extra = "allow"

@root_validator(pre=True)
def validate_extensions(cls, values):
if "stac_extensions" in values:
for ext in values["stac_extensions"]:
if ext in ("collection-assets", "item-assets", "version"):
ext_model = Extensions.get(ext)
ext_model(**values)
return values

def to_dict(self, **kwargs):
return self.dict(by_alias=True, exclude_unset=True, **kwargs)

Expand Down
26 changes: 14 additions & 12 deletions stac_pydantic/collection.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,55 @@
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel
from pydantic import BaseModel, Field, constr

from stac_pydantic.catalog import Catalog
from stac_pydantic.shared import NumType, Provider
from stac_pydantic.shared import Asset, NumType, Provider


class SpatialExtent(BaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/collection-spec/collection-spec.md#spatial-extent-object
https://github.com/radiantearth/stac-spec/blob/v1.0.0/collection-spec/collection-spec.md#spatial-extent-object
"""

bbox: List[List[NumType]]


class TimeInterval(BaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/collection-spec/collection-spec.md#temporal-extent-object
https://github.com/radiantearth/stac-spec/blob/v1.0.0/collection-spec/collection-spec.md#temporal-extent-object
"""

interval: List[List[Union[str, None]]]


class Extent(BaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/collection-spec/collection-spec.md#extent-object
https://github.com/radiantearth/stac-spec/blob/v1.0.0/collection-spec/collection-spec.md#extent-object
"""

spatial: SpatialExtent
temporal: TimeInterval


class Stats(BaseModel):
class Range(BaseModel):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/collection-spec/collection-spec.md#stats-object
https://github.com/radiantearth/stac-spec/blob/v1.0.0/collection-spec/collection-spec.md#stats-object
"""

min: Union[NumType, str]
max: Union[NumType, str]
minimum: Union[NumType, str]
maximum: Union[NumType, str]


class Collection(Catalog):
"""
https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.1/collection-spec/collection-spec.md
https://github.com/radiantearth/stac-spec/blob/v1.0.0/collection-spec/collection-spec.md
"""

license: str
assets: Optional[Dict[str, Asset]]
license: constr(min_length=1)
extent: Extent
title: Optional[str]
keywords: Optional[List[str]]
providers: Optional[List[Provider]]
summaries: Optional[Dict[str, Union[Stats, List[Any]]]]
summaries: Optional[Dict[str, Union[Range, List[Any], Dict[str, Any]]]]
type: constr(min_length=1) = Field("collection", const=True)
41 changes: 41 additions & 0 deletions stac_pydantic/extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from functools import singledispatch

import jsonschema
import requests

from stac_pydantic import Catalog, Collection, Item


@singledispatch
def validate_extensions(stac_obj, b):
geospatial-jeff marked this conversation as resolved.
Show resolved Hide resolved
raise NotImplementedError("Unsupported type")


@validate_extensions.register
def _(stac_obj: dict, reraise_exception: bool = False, **kwargs) -> bool:
try:
if stac_obj["stac_extensions"]:
for ext in stac_obj["stac_extensions"]:
req = requests.get(ext)
schema = req.json()
jsonschema.validate(instance=stac_obj, schema=schema)
except Exception:
if reraise_exception:
raise
return False
return True


@validate_extensions.register
def _(stac_obj: Item, reraise_exception: bool = False, **kwargs) -> bool:
validate_extensions(stac_obj.dict(), reraise_exception)


@validate_extensions.register
def _(stac_obj: Collection, reraise_exception: bool = False, **kwargs) -> bool:
validate_extensions(stac_obj.dict(), reraise_exception)


@validate_extensions.register
def _(stac_obj: Catalog, reraise_exception: bool = False, **kwargs) -> bool:
validate_extensions(stac_obj.dict(), reraise_exception)
52 changes: 0 additions & 52 deletions stac_pydantic/extensions/__init__.py

This file was deleted.

13 changes: 0 additions & 13 deletions stac_pydantic/extensions/collection_assets.py

This file was deleted.

77 changes: 0 additions & 77 deletions stac_pydantic/extensions/datacube.py

This file was deleted.

Loading