Skip to content

Commit

Permalink
Merge pull request #156 from stac-utils/feature/add-optional-dependen…
Browse files Browse the repository at this point in the history
…cies

add request and jsonschema optional dependencies
  • Loading branch information
vincentsarago authored Jul 9, 2024
2 parents 4272d86 + ffd9c38 commit 92c8a70
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

- Cache remote JSON schemas for extensions (#155, @avbentem)
- add `requests` and `jsonschema` in a **validation** optional dependencies (#156, @vincentsarago)

## 3.1.0 (2024-05-21)

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ For more comprehensive schema validation and robust extension support, use [pyst

```shell
python -m pip install stac-pydantic

# or

python -m pip install stac-pydantic["validation"]
```

For local development:
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ keywords=["stac", "pydantic", "validation"]
authors=[{ name = "Arturo Engineering", email = "[email protected]"}]
license= { text = "MIT" }
requires-python=">=3.8"
dependencies = ["click>=8.1.7", "pydantic>=2.4.1", "geojson-pydantic>=1.0.0"]
dependencies = [
"click>=8.1.7",
"pydantic>=2.4.1",
"geojson-pydantic>=1.0.0",
]
dynamic = ["version", "readme"]

[project.scripts]
Expand All @@ -31,6 +35,8 @@ homepage = "https://github.com/stac-utils/stac-pydantic"
repository ="https://github.com/stac-utils/stac-pydantic.git"

[project.optional-dependencies]
validation = ["jsonschema>=4.19.1", "requests>=2.31.0"]

dev = [
"pytest>=7.4.2",
"pytest-cov>=4.1.0",
Expand Down
21 changes: 14 additions & 7 deletions stac_pydantic/extensions.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import json
from functools import lru_cache
from typing import Any, Dict, Union

import jsonschema
import requests

from stac_pydantic.catalog import Catalog
from stac_pydantic.collection import Collection
from stac_pydantic.item import Item

try:
import requests
except ImportError: # pragma: nocover
requests = None # type: ignore

try:
import jsonschema
except ImportError: # pragma: nocover
jsonschema = None # type: ignore


@lru_cache(maxsize=128)
def _fetch_and_cache_schema(url: str) -> dict:
Expand All @@ -25,12 +31,13 @@ def validate_extensions(
Fetch the remote JSON schema, if not already cached, and validate the STAC
object against that schema.
"""
assert requests is not None, "requests must be installed to validate extensions"
assert jsonschema is not None, "jsonschema must be installed to validate extensions"

if isinstance(stac_obj, dict):
stac_dict = stac_obj
else:
# can't use `stac_obj.model_dump()` here
# b/c jsonschema expects pure string representations, not python types
stac_dict = json.loads(stac_obj.model_dump_json())
stac_dict = stac_obj.model_dump(mode="json")

try:
if stac_dict["stac_extensions"]:
Expand Down
17 changes: 16 additions & 1 deletion stac_pydantic/scripts/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
from stac_pydantic.extensions import validate_extensions
from stac_pydantic.item import Item

try:
import requests
except ImportError: # pragma: nocover
requests = None # type: ignore

try:
import jsonschema
except ImportError: # pragma: nocover
jsonschema = None # type: ignore


@click.group(short_help="Validate STAC")
def app() -> None:
Expand All @@ -16,14 +26,19 @@ def app() -> None:
@click.argument("infile")
def validate_item(infile: str) -> None:
"""Validate stac item"""
assert requests is not None, "requests must be installed to validate items"
assert jsonschema is not None, "jsonschema must be installed to validate items"

r = requests.get(infile)
r.raise_for_status()

stac_item = r.json()
try:
item = Item(**stac_item)
item = Item.model_validate(stac_item)
validate_extensions(item, reraise_exception=True)
except ValidationError as e:
click.echo(str(e))
return

click.echo(f"{infile} is valid")
return

0 comments on commit 92c8a70

Please sign in to comment.