Skip to content

Commit

Permalink
Merge pull request #118 from developmentseed/updateRasterVectorPydant…
Browse files Browse the repository at this point in the history
…ic1.0

update titiler-pgstac and tipg to last version compatible with pydantic 1.0
  • Loading branch information
vincentsarago authored Aug 3, 2023
2 parents 7b429e8 + 5df83ce commit d36b50f
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests/test_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_mosaic_api():
assert list(resp.json()[0]) == ["id", "bbox", "assets", "collection"]
assert resp.json()[0]["id"] == "20200307aC0853900w361030"

resp = httpx.get(f"{raster_endpoint}/mosaic/{searchid}/15/8589/12849/assets")
resp = httpx.get(f"{raster_endpoint}/mosaic/{searchid}/tiles/15/8589/12849/assets")
assert resp.status_code == 200
assert len(resp.json()) == 1
assert list(resp.json()[0]) == ["id", "bbox", "assets", "collection"]
Expand Down
8 changes: 8 additions & 0 deletions infrastructure/aws/handlers/raster_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@

from eoapi.raster.app import app
from mangum import Mangum
from titiler.pgstac.db import connect_to_db

logging.getLogger("mangum.lifespan").setLevel(logging.ERROR)
logging.getLogger("mangum.http").setLevel(logging.ERROR)


@app.on_event("startup")
async def startup_event() -> None:
"""Connect to database on startup."""
await connect_to_db(app)


handler = Mangum(app, lifespan="off")

if "AWS_EXECUTION_ENV" in os.environ:
Expand Down
8 changes: 8 additions & 0 deletions infrastructure/aws/handlers/stac_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@

from eoapi.stac.app import app
from mangum import Mangum
from stac_fastapi.pgstac.db import connect_to_db

logging.getLogger("mangum.lifespan").setLevel(logging.ERROR)
logging.getLogger("mangum.http").setLevel(logging.ERROR)


@app.on_event("startup")
async def startup_event() -> None:
"""Connect to database on startup."""
await connect_to_db(app)


handler = Mangum(app, lifespan="off")

if "AWS_EXECUTION_ENV" in os.environ:
Expand Down
107 changes: 57 additions & 50 deletions runtime/eoapi/raster/eoapi/raster/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""TiTiler+PgSTAC FastAPI application."""

import logging
from contextlib import asynccontextmanager
from typing import Dict

import pystac
Expand All @@ -17,7 +18,6 @@
from titiler.core.errors import DEFAULT_STATUS_CODES, add_exception_handlers
from titiler.core.factory import AlgorithmFactory, MultiBaseTilerFactory, TMSFactory
from titiler.core.middleware import CacheControlMiddleware
from titiler.core.resources.enums import OptionalHeader
from titiler.mosaic.errors import MOSAIC_STATUS_CODES
from titiler.pgstac.db import close_db_connection, connect_to_db
from titiler.pgstac.dependencies import ItemPathParams
Expand All @@ -40,19 +40,53 @@
templates = Jinja2Templates(directory=str(resources_files(__package__) / "templates")) # type: ignore


if settings.debug:
optional_headers = [OptionalHeader.server_timing, OptionalHeader.x_assets]
else:
optional_headers = []
@asynccontextmanager
async def lifespan(app: FastAPI):
"""FastAPI Lifespan."""
# Create Connection Pool
await connect_to_db(app)
yield
# Close the Connection Pool
await close_db_connection(app)


app = FastAPI(title=settings.name, version=eoapi_raster_version)
app = FastAPI(
title=settings.name,
version=eoapi_raster_version,
root_path=settings.root_path,
lifespan=lifespan,
)
add_exception_handlers(app, DEFAULT_STATUS_CODES)
add_exception_handlers(app, MOSAIC_STATUS_CODES)

if settings.cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["GET", "POST", "OPTIONS"],
allow_headers=["*"],
)

app.add_middleware(
CacheControlMiddleware,
cachecontrol=settings.cachecontrol,
exclude_path={r"/healthz"},
)
app.add_middleware(
CompressionMiddleware,
exclude_mediatype={
"image/jpeg",
"image/jpg",
"image/png",
"image/jp2",
"image/webp",
},
)

###############################################################################
# MOSAIC Endpoints
mosaic = MosaicTilerFactory(
optional_headers=optional_headers,
router_prefix="/mosaic",
add_statistics=True,
# add /map viewer
Expand Down Expand Up @@ -93,7 +127,6 @@ async def list_collection(request: Request):
stac = MultiBaseTilerFactory(
reader=PgSTACReader,
path_dependency=ItemPathParams,
optional_headers=optional_headers,
router_prefix="/collections/{collection_id}/items/{item_id}",
# add /map viewer
add_viewer=True,
Expand Down Expand Up @@ -178,25 +211,37 @@ def landing(request: Request):
"rel": "service-doc",
},
{
"title": "Mosaic List (JSON)",
"title": "STAC Item Asset's Info (template URL)",
"href": stac.url_for(request, "info"),
"type": "application/json",
"rel": "data",
},
{
"title": "STAC Item Viewer (template URL)",
"href": stac.url_for(request, "viewer"),
"type": "text/html",
"rel": "data",
},
{
"title": "STAC Mosaic List (JSON)",
"href": mosaic.url_for(request, "list_mosaic"),
"type": "application/json",
"rel": "data",
},
{
"title": "Mosaic Builder",
"title": "STAC Mosaic Builder",
"href": mosaic.url_for(request, "mosaic_builder"),
"type": "text/html",
"rel": "data",
},
{
"title": "Mosaic Metadata (template URL)",
"title": "STAC Mosaic Metadata (template URL)",
"href": mosaic.url_for(request, "info_search", searchid="{searchid}"),
"type": "application/json",
"rel": "data",
},
{
"title": "Mosaic viewer (template URL)",
"title": "STAC Mosaic viewer (template URL)",
"href": mosaic.url_for(request, "map_viewer", searchid="{searchid}"),
"type": "text/html",
"rel": "data",
Expand Down Expand Up @@ -240,41 +285,3 @@ def landing(request: Request):
"urlparams": str(request.url.query),
},
)


if settings.cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["GET", "POST", "OPTIONS"],
allow_headers=["*"],
)

app.add_middleware(
CacheControlMiddleware,
cachecontrol=settings.cachecontrol,
exclude_path={r"/healthz"},
)
app.add_middleware(
CompressionMiddleware,
exclude_mediatype={
"image/jpeg",
"image/jpg",
"image/png",
"image/jp2",
"image/webp",
},
)


@app.on_event("startup")
async def startup_event() -> None:
"""Connect to database on startup."""
await connect_to_db(app)


@app.on_event("shutdown")
async def shutdown_event() -> None:
"""Close database connection."""
await close_db_connection(app)
18 changes: 2 additions & 16 deletions runtime/eoapi/raster/eoapi/raster/config.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
"""API settings."""

from functools import lru_cache

import pydantic


class _ApiSettings(pydantic.BaseSettings):
class ApiSettings(pydantic.BaseSettings):
"""API settings"""

name: str = "eoAPI-raster"
cors_origins: str = "*"
cachecontrol: str = "public, max-age=3600"
debug: bool = False
root_path: str = ""

@pydantic.validator("cors_origins")
def parse_cors_origin(cls, v):
Expand All @@ -23,16 +22,3 @@ class Config:

env_file = ".env"
env_prefix = "EOAPI_RASTER_"


@lru_cache()
def ApiSettings() -> _ApiSettings:
"""
This function returns a cached instance of the APISettings object.
Caching is used to prevent re-reading the environment every time the API settings are used in an endpoint.
If you want to change an environment variable and reset the cache (e.g., during testing), this can be done
using the `lru_cache` instance method `get_api_settings.cache_clear()`.
From https://github.com/dmontagu/fastapi-utils/blob/af95ff4a8195caaa9edaa3dbd5b6eeb09691d9c7/fastapi_utils/api_settings.py#L60-L69
"""
return _ApiSettings()
2 changes: 1 addition & 1 deletion runtime/eoapi/raster/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"titiler.pgstac==0.4.1",
"titiler.pgstac==0.5.1",
"starlette-cramjam>=0.3,<0.4",
"importlib_resources>=1.1.0;python_version<'3.9'",
]
Expand Down
26 changes: 13 additions & 13 deletions runtime/eoapi/stac/eoapi/stac/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""FastAPI application using PGStac."""

from contextlib import asynccontextmanager

from eoapi.stac.config import ApiSettings, TilesApiSettings
from eoapi.stac.config import extensions as PgStacExtensions
from eoapi.stac.config import get_request_model as GETModel
Expand Down Expand Up @@ -31,8 +33,18 @@
settings = Settings()


@asynccontextmanager
async def lifespan(app: FastAPI):
"""FastAPI Lifespan."""
# Create Connection Pool
await connect_to_db(app)
yield
# Close the Connection Pool
await close_db_connection(app)


api = StacApi(
app=FastAPI(title=api_settings.name),
app=FastAPI(title=api_settings.name, lifespan=lifespan),
title=api_settings.name,
description=api_settings.name,
settings=settings,
Expand Down Expand Up @@ -69,15 +81,3 @@ async def viewer_page(request: Request):
{"request": request, "endpoint": str(request.url).replace("/index.html", "")},
media_type="text/html",
)


@app.on_event("startup")
async def startup_event():
"""Connect to database on startup."""
await connect_to_db(app)


@app.on_event("shutdown")
async def shutdown_event():
"""Close database connection."""
await close_db_connection(app)
3 changes: 3 additions & 0 deletions runtime/eoapi/stac/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"fastapi>=0.95.1",
"pydantic~=1.0",
"geojson-pydantic~=0.6",
"stac-fastapi.api~=2.4",
"stac-fastapi.types~=2.4",
"stac-fastapi.extensions~=2.4",
Expand Down
2 changes: 1 addition & 1 deletion runtime/eoapi/vector/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"tipg==0.2.0",
"tipg==0.3.0",
]

[project.optional-dependencies]
Expand Down

0 comments on commit d36b50f

Please sign in to comment.