Skip to content

Commit

Permalink
update queryparam
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago committed May 17, 2022
1 parent 523ccba commit 28afbd8
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 70 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ cdk.out/
.idea/

benchmark/

.pgdata/
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ services:
ports:
- "5439:5432"
command: postgres -N 500
volumes:
- ./.pgdata:/var/lib/postgresql/data
39 changes: 27 additions & 12 deletions tifeatures/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"""tifeatures dependencies."""

import re
from typing import Optional

from geojson_pydantic.geometries import Polygon
from typing import List, Optional

from tifeatures.layer import CollectionLayer
from tifeatures.resources.enums import AcceptType, ResponseType
Expand Down Expand Up @@ -48,24 +46,41 @@ def CollectionParams(


def bbox_query(
intersects: Optional[str] = Query(
bbox: Optional[str] = Query(
None,
alias="bbox",
description="Filter features in response to ones intersecting a bounding box",
description="Spatial Filter.",
)
) -> Optional[Polygon]:
) -> Optional[List[float]]:
"""BBox dependency."""
if intersects:
split_bbox = intersects.split(",")
if len(split_bbox) not in [4, 6]:
if bbox:
bounds = list(map(float, bbox.split(",")))
if len(bounds) == 4:
if abs(bounds[0]) > 180 or abs(bounds[2]) > 180:
raise ValueError(f"Invalid longitude in bbox: {bounds}")
if abs(bounds[1]) > 90 or abs(bounds[3]) > 90:
raise ValueError(f"Invalid latitude in bbox: {bounds}")

elif len(bounds) == 6:
if abs(bounds[0]) > 180 or abs(bounds[3]) > 180:
raise ValueError(f"Invalid longitude in bbox: {bounds}")
if abs(bounds[1]) > 90 or abs(bounds[4]) > 90:
raise ValueError(f"Invalid latitude in bbox: {bounds}")
else:
raise Exception("Invalid BBOX.")

bounds = tuple(map(float, split_bbox))
return Polygon.from_bounds(*bounds)
return bounds

return None


def datetime_query(
datetime: Optional[str] = Query(None, description="Temporal Filter."),
) -> Optional[str]:
"""Datetime dependency."""
# TODO validation / format
return datetime


def OutputType(
request: Request,
f: Optional[ResponseType] = Query(None, description="Response MediaType."),
Expand Down
72 changes: 20 additions & 52 deletions tifeatures/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import json
import pathlib
from dataclasses import dataclass, field
from typing import Any, Callable, Optional

from geojson_pydantic.geometries import Polygon
from typing import Any, Callable, List, Optional

from tifeatures import model
from tifeatures.dependencies import CollectionParams, OutputType, bbox_query
from tifeatures.dependencies import (
CollectionParams,
OutputType,
bbox_query,
datetime_query,
)
from tifeatures.errors import NotFound
from tifeatures.layer import CollectionLayer
from tifeatures.resources.enums import MediaType, ResponseType
Expand Down Expand Up @@ -392,66 +395,31 @@ async def items(
ge=0,
description="Starts the response at an offset.",
),
intersects: Optional[Polygon] = Depends(bbox_query),
bbox: Optional[List[float]] = Depends(bbox_query),
datetime: Optional[str] = Depends(datetime_query),
properties: Optional[str] = Query(
None,
description="Return only specific properties (comma-separated). If PROP-LIST is empty, no properties are returned. If not present, all properties are returned.",
),
sortby: Optional[str] = Query(
None,
description="Sort the response items by a property (ascending (default) or descending).",
),
output_type: Optional[ResponseType] = Depends(OutputType),
):
offset = offset or 0

# req ={}
# if bbox:
# req["filter"]["args"].append(
# {
# "op": "s_intersects",
# "args": [{"property": "geometry"}, bbox.dict()],
# }
# )
# # <propname>=val - filter features for a property having a value. Multiple property filters are ANDed together.
# qs_key_to_remove = ["limit", "offset", "bbox", "properties", "sortby"]
# propname = [
# <NAME>=VALUE - filter features for a property having a value. Multiple property filters are ANDed together.
# qs_key_to_remove = [
# "limit",
# "offset",
# "bbox",
# "datetime",
# "properties",
# "f",
# ]
# properties_filter = [
# {"op": "eq", "args": [{"property": key}, value]}
# for (key, value) in request.query_params.items()
# if key.lower() not in qs_key_to_remove
# ]
# if propname:
# req["filter"]["args"].append(*propname)
#
# # sortby=[+|-]PROP - sort the response items by a property (ascending (default) or descending).
# if sortby:
# sort_expr = []
# for s in sortby.split(","):
# parts = re.match(
# "^(?P<dir>[+-]?)(?P<prop>.*)$", s
# ).groupdict() # type:ignore
# sort_expr.append(
# {
# "field": f"properties.{parts['prop']}",
# "direction": "desc" if parts["dir"] == "-" else "asc",
# }
# )
# req["sortby"] = sort_expr
# # properties=PROP-LIST- return only specific properties (comma-separated). If PROP-LIST is empty, no properties are returned. If not present, all properties are returned.
# if properties is not None:
# if properties == "":
# req["fields"]["exclude"].append("properties")
# else:
# required_props = ["type", "geometry", "id", "bbox", "assets"]
# req["fields"].update(
# {
# "include": required_props
# + [f"properties.{p}" for p in properties.split(",")]
# }
# )

# TODO: create filter using bbox/properties by using pygeofilter
# TODO: use sortby

items = await collection.features(
request.app.state.pool,
limit=limit,
Expand Down
12 changes: 6 additions & 6 deletions tifeatures/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class CollectionLayer(BaseModel, metaclass=abc.ABCMeta):
async def features(
self,
pool: asyncpg.BuildPgPool,
limit: int = None,
offset: int = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
**kwargs: Any,
) -> Items:
"""Return a FeatureCollection."""
Expand Down Expand Up @@ -82,8 +82,8 @@ class Table(CollectionLayer):
async def features(
self,
pool: asyncpg.BuildPgPool,
limit: int = None,
offset: int = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
**kwargs: Any,
) -> Items:
"""Return a FeatureCollection."""
Expand Down Expand Up @@ -226,8 +226,8 @@ def from_file(cls, id: str, infile: str, **kwargs: Any):
async def features(
self,
pool: asyncpg.BuildPgPool,
limit: int = None,
offset: int = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
**kwargs: Any,
) -> FeatureCollection:
"""Return a FeatureCollection."""
Expand Down

0 comments on commit 28afbd8

Please sign in to comment.