Revert pydantic models to v1 version (#1584)
* Revert pydantic models to v1 version Revert pydantic models to v1 version Revert pydantic models to v1 version Revert pydantic models to v1 version * Add initial tests for models Add initial tests for models * Revert pydantic models to v1 version Revert pydantic models to v1 version Revert pydantic models to v1 version Revert pydantic models to v1 version * Add initial tests for models Add initial tests for models * Fix and replace methods from pydantic v2 * Add more tests for cql models
This commit is contained in:
committed by
GitHub
parent
54688969b0
commit
e69a9744a2
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
# Francesco Bartoli <xbartolone@gmail.com>
|
# Francesco Bartoli <xbartolone@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Tom Kralidis
|
# Copyright (c) 2022 Tom Kralidis
|
||||||
# Copyright (c) 2023 Francesco Bartoli
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
# =================================================================
|
# =================================================================
|
||||||
#
|
#
|
||||||
# Authors: Sander Schaminee <sander.schaminee@geocat.net>
|
# Authors: Sander Schaminee <sander.schaminee@geocat.net>
|
||||||
|
# Francesco Bartoli <xbartolone@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Sander Schaminee
|
# Copyright (c) 2023 Sander Schaminee
|
||||||
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
@@ -34,7 +36,7 @@ from pydantic import BaseModel, Field
|
|||||||
|
|
||||||
class APIRules(BaseModel):
|
class APIRules(BaseModel):
|
||||||
""" Pydantic model for API design rules that must be adhered to. """
|
""" Pydantic model for API design rules that must be adhered to. """
|
||||||
api_version: str = Field(pattern=r'^\d+\.\d+\..+$',
|
api_version: str = Field(regex=r'^\d+\.\d+\..+$',
|
||||||
description="Semantic API version number.")
|
description="Semantic API version number.")
|
||||||
url_prefix: str = Field(
|
url_prefix: str = Field(
|
||||||
"",
|
"",
|
||||||
@@ -60,11 +62,11 @@ class APIRules(BaseModel):
|
|||||||
""" Returns a new APIRules instance for the current API version
|
""" Returns a new APIRules instance for the current API version
|
||||||
and configured rules. """
|
and configured rules. """
|
||||||
obj = {
|
obj = {
|
||||||
k: v for k, v in rules_config.items() if k in APIRules.model_fields
|
k: v for k, v in rules_config.items() if k in APIRules.__fields__
|
||||||
}
|
}
|
||||||
# Validation will fail if required `api_version` is missing
|
# Validation will fail if required `api_version` is missing
|
||||||
# or if `api_version` is not a semantic version number
|
# or if `api_version` is not a semantic version number
|
||||||
return APIRules.model_validate(obj)
|
return APIRules.parse_obj(obj)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def response_headers(self) -> dict:
|
def response_headers(self) -> dict:
|
||||||
|
|||||||
+128
-128
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Francesco Bartoli
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
@@ -35,11 +35,11 @@
|
|||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import Any, List, Literal, Optional, Union
|
from typing import Any, List, Literal, Optional, Union
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, RootModel
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
class CQLModel(RootModel):
|
class CQLModel(BaseModel):
|
||||||
root: 'Union[\n ComparisonPredicate,\n SpatialPredicate,\n TemporalPredicate,\n AndExpression\n ]'
|
__root__: 'Union[\n ComparisonPredicate,\n SpatialPredicate,\n TemporalPredicate,\n AndExpression\n ]'
|
||||||
|
|
||||||
|
|
||||||
class AndExpression(BaseModel):
|
class AndExpression(BaseModel):
|
||||||
@@ -58,16 +58,16 @@ class PropertyRef(BaseModel):
|
|||||||
property: 'Optional[str]' = None
|
property: 'Optional[str]' = None
|
||||||
|
|
||||||
|
|
||||||
class ScalarLiteral(RootModel):
|
class ScalarLiteral(BaseModel):
|
||||||
root: 'Union[str, float, bool]'
|
__root__: 'Union[str, float, bool]'
|
||||||
|
|
||||||
|
|
||||||
class Bbox(RootModel):
|
class Bbox(BaseModel):
|
||||||
root: 'List[float]'
|
__root__: 'List[float]'
|
||||||
|
|
||||||
|
|
||||||
class LinestringCoordinate(RootModel):
|
class LinestringCoordinate(BaseModel):
|
||||||
root: 'List[Any]'
|
__root__: 'List[Any]'
|
||||||
|
|
||||||
|
|
||||||
class Linestring(BaseModel):
|
class Linestring(BaseModel):
|
||||||
@@ -76,8 +76,8 @@ class Linestring(BaseModel):
|
|||||||
bbox: 'Optional[List[float]]' = Field(None)
|
bbox: 'Optional[List[float]]' = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class MultilineStringCoordinate(RootModel):
|
class MultilineStringCoordinate(BaseModel):
|
||||||
root: 'List[Any]'
|
__root__: 'List[Any]'
|
||||||
|
|
||||||
|
|
||||||
class Multilinestring(BaseModel):
|
class Multilinestring(BaseModel):
|
||||||
@@ -92,8 +92,8 @@ class Multipoint(BaseModel):
|
|||||||
bbox: 'Optional[List[float]]' = Field(None)
|
bbox: 'Optional[List[float]]' = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class MultipolygonCoordinateItem(RootModel):
|
class MultipolygonCoordinateItem(BaseModel):
|
||||||
root: 'List[Any]'
|
__root__: 'List[Any]'
|
||||||
|
|
||||||
|
|
||||||
class Multipolygon(BaseModel):
|
class Multipolygon(BaseModel):
|
||||||
@@ -108,8 +108,8 @@ class Point(BaseModel):
|
|||||||
bbox: 'Optional[List[float]]' = Field(None)
|
bbox: 'Optional[List[float]]' = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class PolygonCoordinatesItem(RootModel):
|
class PolygonCoordinatesItem(BaseModel):
|
||||||
root: 'List[Any]'
|
__root__: 'List[Any]'
|
||||||
|
|
||||||
|
|
||||||
class Polygon(BaseModel):
|
class Polygon(BaseModel):
|
||||||
@@ -118,56 +118,56 @@ class Polygon(BaseModel):
|
|||||||
bbox: 'Optional[List[float]]' = Field(None)
|
bbox: 'Optional[List[float]]' = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class TimeString(RootModel):
|
class TimeString(BaseModel):
|
||||||
root: 'Union[date, datetime]'
|
__root__: 'Union[date, datetime]'
|
||||||
|
|
||||||
|
|
||||||
class EnvelopeLiteral(BaseModel):
|
class EnvelopeLiteral(BaseModel):
|
||||||
bbox: 'Bbox'
|
bbox: 'Bbox'
|
||||||
|
|
||||||
|
|
||||||
class GeometryLiteral(RootModel):
|
class GeometryLiteral(BaseModel):
|
||||||
root: 'Union[\n Point, Linestring, Polygon, Multipoint, Multilinestring, Multipolygon\n ]'
|
__root__: 'Union[\n Point,\n Linestring,\n Polygon,\n Multipoint,\n Multilinestring,\n Multipolygon\n ]'
|
||||||
|
|
||||||
|
|
||||||
class TypedTimeString(BaseModel):
|
class TypedTimeString(BaseModel):
|
||||||
datetime: 'TimeString'
|
datetime: 'TimeString'
|
||||||
|
|
||||||
|
|
||||||
class PeriodString(RootModel):
|
class PeriodString(BaseModel):
|
||||||
root: 'List[Union[TimeString, str]]' = Field(...)
|
__root__: 'List[Union[TimeString, str]]' = Field(...)
|
||||||
|
|
||||||
|
|
||||||
class SpatialLiteral(RootModel):
|
class SpatialLiteral(BaseModel):
|
||||||
root: 'Union[GeometryLiteral, EnvelopeLiteral]'
|
__root__: 'Union[GeometryLiteral, EnvelopeLiteral]'
|
||||||
|
|
||||||
|
|
||||||
class TemporalLiteral(RootModel):
|
class TemporalLiteral(BaseModel):
|
||||||
root: 'Union[TimeString, PeriodString]'
|
__root__: 'Union[TimeString, PeriodString]'
|
||||||
|
|
||||||
|
|
||||||
class TypedPeriodString(BaseModel):
|
class TypedPeriodString(BaseModel):
|
||||||
datetime: 'PeriodString'
|
datetime: 'PeriodString'
|
||||||
|
|
||||||
|
|
||||||
class TypedTemporalLiteral(RootModel):
|
class TypedTemporalLiteral(BaseModel):
|
||||||
root: 'Union[TypedTimeString, TypedPeriodString]'
|
__root__: 'Union[TypedTimeString, TypedPeriodString]'
|
||||||
|
|
||||||
|
|
||||||
class ArrayPredicate(RootModel):
|
class ArrayPredicate(BaseModel):
|
||||||
root: 'Union[\n AequalsExpression,\n AcontainsExpression,\n AcontainedByExpression,\n AoverlapsExpression,\n ]'
|
__root__: 'Union[\n AequalsExpression,\n AcontainsExpression,\n AcontainedByExpression,\n AoverlapsExpression,\n ]'
|
||||||
|
|
||||||
|
|
||||||
class ComparisonPredicate(RootModel):
|
class ComparisonPredicate(BaseModel):
|
||||||
root: 'Union[\n BinaryComparisonPredicate,\n IsLikePredicate,\n IsBetweenPredicate,\n IsInListPredicate,\n IsNullPredicate,\n ]'
|
__root__: 'Union[\n BinaryComparisonPredicate,\n IsLikePredicate,\n IsBetweenPredicate,\n IsInListPredicate,\n IsNullPredicate,\n ]'
|
||||||
|
|
||||||
|
|
||||||
class SpatialPredicate(RootModel):
|
class SpatialPredicate(BaseModel):
|
||||||
root: 'Union[\n IntersectsExpression,\n EqualsExpression,\n DisjointExpression,\n TouchesExpression,\n WithinExpression,\n OverlapsExpression,\n CrossesExpression,\n ContainsExpression,\n ]'
|
__root__: 'Union[\n IntersectsExpression,\n EqualsExpression,\n DisjointExpression,\n TouchesExpression,\n WithinExpression,\n OverlapsExpression,\n CrossesExpression,\n ContainsExpression,\n ]'
|
||||||
|
|
||||||
|
|
||||||
class TemporalPredicate(RootModel):
|
class TemporalPredicate(BaseModel):
|
||||||
root: 'Union[\n BeforeExpression,\n AfterExpression,\n MeetsExpression,\n MetbyExpression,\n ToverlapsExpression,\n OverlappedbyExpression,\n BeginsExpression,\n BegunbyExpression,\n DuringExpression,\n TcontainsExpression,\n EndsExpression,\n EndedbyExpression,\n TequalsExpression,\n AnyinteractsExpression,\n ]'
|
__root__: 'Union[\n BeforeExpression,\n AfterExpression,\n MeetsExpression,\n MetbyExpression,\n ToverlapsExpression,\n OverlappedbyExpression,\n BeginsExpression,\n BegunbyExpression,\n DuringExpression,\n TcontainsExpression,\n EndsExpression,\n EndedbyExpression,\n TequalsExpression,\n AnyinteractsExpression,\n ]'
|
||||||
|
|
||||||
|
|
||||||
class AcontainedByExpression(BaseModel):
|
class AcontainedByExpression(BaseModel):
|
||||||
@@ -206,8 +206,8 @@ class BegunbyExpression(BaseModel):
|
|||||||
begunby: 'TemporalOperands'
|
begunby: 'TemporalOperands'
|
||||||
|
|
||||||
|
|
||||||
class BinaryComparisonPredicate(RootModel):
|
class BinaryComparisonPredicate(BaseModel):
|
||||||
root: 'Union[\n EqExpression, LtExpression, GtExpression, LteExpression, GteExpression\n ]'
|
__root__: 'Union[\n EqExpression, LtExpression, GtExpression, LteExpression, GteExpression\n ]'
|
||||||
|
|
||||||
|
|
||||||
class ContainsExpression(BaseModel):
|
class ContainsExpression(BaseModel):
|
||||||
@@ -244,8 +244,8 @@ class IntersectsExpression(BaseModel):
|
|||||||
|
|
||||||
class Between(BaseModel):
|
class Between(BaseModel):
|
||||||
value: 'ValueExpression'
|
value: 'ValueExpression'
|
||||||
lower: 'Optional[ScalarExpression]' = Field(None)
|
lower: 'ScalarExpression' = Field(None)
|
||||||
upper: 'Optional[ScalarExpression]' = Field(None)
|
upper: 'ScalarExpression' = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class IsBetweenPredicate(BaseModel):
|
class IsBetweenPredicate(BaseModel):
|
||||||
@@ -310,8 +310,8 @@ class WithinExpression(BaseModel):
|
|||||||
within: 'SpatialOperands'
|
within: 'SpatialOperands'
|
||||||
|
|
||||||
|
|
||||||
class ArrayExpression(RootModel):
|
class ArrayExpression(BaseModel):
|
||||||
root: 'List[Union[PropertyRef, FunctionRef, ArrayLiteral]]' = Field(
|
__root__: 'List[Union[PropertyRef, FunctionRef, ArrayLiteral]]' = Field(
|
||||||
... # , max_items=2, min_items=2
|
... # , max_items=2, min_items=2
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -336,45 +336,45 @@ class LteExpression(BaseModel):
|
|||||||
lte: 'ScalarOperands'
|
lte: 'ScalarOperands'
|
||||||
|
|
||||||
|
|
||||||
class ScalarExpression(RootModel):
|
class ScalarExpression(BaseModel):
|
||||||
root: 'Union[ScalarLiteral, PropertyRef,\n FunctionRef, ArithmeticExpression]'
|
__root__: 'Union[ScalarLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression]'
|
||||||
|
|
||||||
|
|
||||||
class ScalarOperands(RootModel):
|
class ScalarOperands(BaseModel):
|
||||||
root: 'List[ScalarExpression]' = Field(...)
|
__root__: 'List[ScalarExpression]' = Field(...)
|
||||||
|
|
||||||
|
|
||||||
class SpatialOperands(RootModel):
|
class SpatialOperands(BaseModel):
|
||||||
root: 'List[GeomExpression]' = Field(...)
|
__root__: 'List[GeomExpression]' = Field(...)
|
||||||
|
|
||||||
|
|
||||||
class TemporalOperands(RootModel):
|
class TemporalOperands(BaseModel):
|
||||||
root: 'List[TemporalExpression]' = Field(...)
|
__root__: 'List[TemporalExpression]' = Field(...)
|
||||||
# , max_items=2, min_items=2)
|
# , max_items=2, min_items=2)
|
||||||
|
|
||||||
|
|
||||||
class ValueExpression(RootModel):
|
class ValueExpression(BaseModel):
|
||||||
root: 'Union[ScalarExpression, SpatialLiteral, TypedTemporalLiteral]'
|
__root__: 'Union[ScalarExpression, SpatialLiteral, TypedTemporalLiteral]'
|
||||||
|
|
||||||
|
|
||||||
class ArithmeticExpression(RootModel):
|
class ArithmeticExpression(BaseModel):
|
||||||
root: 'Union[AddExpression, SubExpression, MulExpression, DivExpression]'
|
__root__: 'Union[AddExpression, SubExpression, MulExpression, DivExpression]'
|
||||||
|
|
||||||
|
|
||||||
class ArrayLiteral(RootModel):
|
class ArrayLiteral(BaseModel):
|
||||||
root: 'List[\n Union[\n ScalarLiteral,\n SpatialLiteral,\n TypedTemporalLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression,\n ArrayLiteral,\n ]\n ]'
|
__root__: 'List[\n Union[\n ScalarLiteral,\n SpatialLiteral,\n TypedTemporalLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression,\n ArrayLiteral,\n ]\n ]'
|
||||||
|
|
||||||
|
|
||||||
class FunctionRef(BaseModel):
|
class FunctionRef(BaseModel):
|
||||||
function: 'Function'
|
function: 'Function'
|
||||||
|
|
||||||
|
|
||||||
class GeomExpression(RootModel):
|
class GeomExpression(BaseModel):
|
||||||
root: 'Union[SpatialLiteral, PropertyRef, FunctionRef]'
|
__root__: 'Union[SpatialLiteral, PropertyRef, FunctionRef]'
|
||||||
|
|
||||||
|
|
||||||
class TemporalExpression(RootModel):
|
class TemporalExpression(BaseModel):
|
||||||
root: 'Union[TemporalLiteral, PropertyRef, FunctionRef]'
|
__root__: 'Union[TemporalLiteral, PropertyRef, FunctionRef]'
|
||||||
|
|
||||||
|
|
||||||
# here
|
# here
|
||||||
@@ -384,7 +384,7 @@ class AddExpression(BaseModel):
|
|||||||
|
|
||||||
# here
|
# here
|
||||||
class DivExpression(BaseModel):
|
class DivExpression(BaseModel):
|
||||||
div_: 'Optional[ArithmeticOperands]' = Field(None, alias='/')
|
div_: 'ArithmeticOperands' = Field(None, alias='/')
|
||||||
|
|
||||||
|
|
||||||
class Function(BaseModel):
|
class Function(BaseModel):
|
||||||
@@ -402,68 +402,68 @@ class SubExpression(BaseModel):
|
|||||||
sub_: 'ArithmeticOperands' = Field(..., alias='-')
|
sub_: 'ArithmeticOperands' = Field(..., alias='-')
|
||||||
|
|
||||||
|
|
||||||
class ArithmeticOperands(RootModel):
|
class ArithmeticOperands(BaseModel):
|
||||||
root: 'List[\n Union[ArithmeticExpression, PropertyRef, FunctionRef, float]\n ]' = Field(...)
|
__root__: 'List[\n Union[ArithmeticExpression, PropertyRef, FunctionRef, float]\n ]' = Field(...)
|
||||||
|
|
||||||
|
|
||||||
CQLModel.model_rebuild()
|
CQLModel.update_forward_refs()
|
||||||
AndExpression.model_rebuild()
|
AndExpression.update_forward_refs()
|
||||||
ArrayPredicate.model_rebuild()
|
ArrayPredicate.update_forward_refs()
|
||||||
ComparisonPredicate.model_rebuild()
|
ComparisonPredicate.update_forward_refs()
|
||||||
SpatialPredicate.model_rebuild()
|
SpatialPredicate.update_forward_refs()
|
||||||
TemporalPredicate.model_rebuild()
|
TemporalPredicate.update_forward_refs()
|
||||||
AcontainedByExpression.model_rebuild()
|
AcontainedByExpression.update_forward_refs()
|
||||||
AcontainsExpression.model_rebuild()
|
AcontainsExpression.update_forward_refs()
|
||||||
AequalsExpression.model_rebuild()
|
AequalsExpression.update_forward_refs()
|
||||||
AfterExpression.model_rebuild()
|
AfterExpression.update_forward_refs()
|
||||||
AnyinteractsExpression.model_rebuild()
|
AnyinteractsExpression.update_forward_refs()
|
||||||
AoverlapsExpression.model_rebuild()
|
AoverlapsExpression.update_forward_refs()
|
||||||
BeforeExpression.model_rebuild()
|
BeforeExpression.update_forward_refs()
|
||||||
BeginsExpression.model_rebuild()
|
BeginsExpression.update_forward_refs()
|
||||||
BegunbyExpression.model_rebuild()
|
BegunbyExpression.update_forward_refs()
|
||||||
BinaryComparisonPredicate.model_rebuild()
|
BinaryComparisonPredicate.update_forward_refs()
|
||||||
ContainsExpression.model_rebuild()
|
ContainsExpression.update_forward_refs()
|
||||||
CrossesExpression.model_rebuild()
|
CrossesExpression.update_forward_refs()
|
||||||
DisjointExpression.model_rebuild()
|
DisjointExpression.update_forward_refs()
|
||||||
DuringExpression.model_rebuild()
|
DuringExpression.update_forward_refs()
|
||||||
EndedbyExpression.model_rebuild()
|
EndedbyExpression.update_forward_refs()
|
||||||
EndsExpression.model_rebuild()
|
EndsExpression.update_forward_refs()
|
||||||
EqualsExpression.model_rebuild()
|
EqualsExpression.update_forward_refs()
|
||||||
IntersectsExpression.model_rebuild()
|
IntersectsExpression.update_forward_refs()
|
||||||
Between.model_rebuild()
|
Between.update_forward_refs()
|
||||||
In.model_rebuild()
|
In.update_forward_refs()
|
||||||
IsBetweenPredicate.model_rebuild()
|
IsBetweenPredicate.update_forward_refs()
|
||||||
IsLikePredicate.model_rebuild()
|
IsLikePredicate.update_forward_refs()
|
||||||
IsNullPredicate.model_rebuild()
|
IsNullPredicate.update_forward_refs()
|
||||||
ValueExpression.model_rebuild()
|
ValueExpression.update_forward_refs()
|
||||||
MeetsExpression.model_rebuild()
|
MeetsExpression.update_forward_refs()
|
||||||
MetbyExpression.model_rebuild()
|
MetbyExpression.update_forward_refs()
|
||||||
OverlappedbyExpression.model_rebuild()
|
OverlappedbyExpression.update_forward_refs()
|
||||||
OverlapsExpression.model_rebuild()
|
OverlapsExpression.update_forward_refs()
|
||||||
TcontainsExpression.model_rebuild()
|
TcontainsExpression.update_forward_refs()
|
||||||
TequalsExpression.model_rebuild()
|
TequalsExpression.update_forward_refs()
|
||||||
TouchesExpression.model_rebuild()
|
TouchesExpression.update_forward_refs()
|
||||||
ToverlapsExpression.model_rebuild()
|
ToverlapsExpression.update_forward_refs()
|
||||||
WithinExpression.model_rebuild()
|
WithinExpression.update_forward_refs()
|
||||||
ArrayExpression.model_rebuild()
|
ArrayExpression.update_forward_refs()
|
||||||
EqExpression.model_rebuild()
|
EqExpression.update_forward_refs()
|
||||||
GtExpression.model_rebuild()
|
GtExpression.update_forward_refs()
|
||||||
GteExpression.model_rebuild()
|
GteExpression.update_forward_refs()
|
||||||
LtExpression.model_rebuild()
|
LtExpression.update_forward_refs()
|
||||||
LteExpression.model_rebuild()
|
LteExpression.update_forward_refs()
|
||||||
ScalarExpression.model_rebuild()
|
ScalarExpression.update_forward_refs()
|
||||||
ScalarOperands.model_rebuild()
|
ScalarOperands.update_forward_refs()
|
||||||
SpatialOperands.model_rebuild()
|
SpatialOperands.update_forward_refs()
|
||||||
TemporalOperands.model_rebuild()
|
TemporalOperands.update_forward_refs()
|
||||||
ArithmeticExpression.model_rebuild()
|
ArithmeticExpression.update_forward_refs()
|
||||||
ArrayLiteral.model_rebuild()
|
ArrayLiteral.update_forward_refs()
|
||||||
ScalarLiteral.model_rebuild()
|
ScalarLiteral.update_forward_refs()
|
||||||
PropertyRef.model_rebuild()
|
PropertyRef.update_forward_refs()
|
||||||
FunctionRef.model_rebuild()
|
FunctionRef.update_forward_refs()
|
||||||
AddExpression.model_rebuild()
|
AddExpression.update_forward_refs()
|
||||||
DivExpression.model_rebuild()
|
DivExpression.update_forward_refs()
|
||||||
MulExpression.model_rebuild()
|
MulExpression.update_forward_refs()
|
||||||
SubExpression.model_rebuild()
|
SubExpression.update_forward_refs()
|
||||||
|
|
||||||
|
|
||||||
def get_next_node(obj):
|
def get_next_node(obj):
|
||||||
@@ -478,25 +478,25 @@ def get_next_node(obj):
|
|||||||
next_node = obj.not_
|
next_node = obj.not_
|
||||||
logical_op = 'not'
|
logical_op = 'not'
|
||||||
elif obj.__repr_name__() == 'ComparisonPredicate':
|
elif obj.__repr_name__() == 'ComparisonPredicate':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'SpatialPredicate':
|
elif obj.__repr_name__() == 'SpatialPredicate':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'TemporalPredicate':
|
elif obj.__repr_name__() == 'TemporalPredicate':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'IsBetweenPredicate':
|
elif obj.__repr_name__() == 'IsBetweenPredicate':
|
||||||
next_node = obj.between
|
next_node = obj.between
|
||||||
elif obj.__repr_name__() == 'Between':
|
elif obj.__repr_name__() == 'Between':
|
||||||
next_node = obj.value
|
next_node = obj.value
|
||||||
elif obj.__repr_name__() == 'ValueExpression':
|
elif obj.__repr_name__() == 'ValueExpression':
|
||||||
next_node = obj.root or obj.lower or obj.upper
|
next_node = obj.__root__ or obj.lower or obj.upper
|
||||||
elif obj.__repr_name__() == 'ScalarExpression':
|
elif obj.__repr_name__() == 'ScalarExpression':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'ScalarLiteral':
|
elif obj.__repr_name__() == 'ScalarLiteral':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'PropertyRef':
|
elif obj.__repr_name__() == 'PropertyRef':
|
||||||
next_node = obj.property
|
next_node = obj.property
|
||||||
elif obj.__repr_name__() == 'BinaryComparisonPredicate':
|
elif obj.__repr_name__() == 'BinaryComparisonPredicate':
|
||||||
next_node = obj.root
|
next_node = obj.__root__
|
||||||
elif obj.__repr_name__() == 'EqExpression':
|
elif obj.__repr_name__() == 'EqExpression':
|
||||||
next_node = obj.eq
|
next_node = obj.eq
|
||||||
logical_op = 'eq'
|
logical_op = 'eq'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2022 Francesco Bartoli
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from pydantic import RootModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class SupportedFormats(Enum):
|
class SupportedFormats(Enum):
|
||||||
@@ -39,5 +39,5 @@ class SupportedFormats(Enum):
|
|||||||
YAML = "yaml"
|
YAML = "yaml"
|
||||||
|
|
||||||
|
|
||||||
class OAPIFormat(RootModel):
|
class OAPIFormat(BaseModel):
|
||||||
root: SupportedFormats = SupportedFormats.YAML
|
__root__: SupportedFormats = SupportedFormats.YAML
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
# =================================================================
|
# =================================================================
|
||||||
#
|
#
|
||||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||||
|
# Francesco Bartoli <xbartolone@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2023 Tom Kralidis
|
# Copyright (c) 2023 Tom Kralidis
|
||||||
# Copyright (c) 2021 Francesco Bartoli
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
@@ -294,7 +295,7 @@ class ElasticsearchProvider(BaseProvider):
|
|||||||
try:
|
try:
|
||||||
LOGGER.debug('querying Elasticsearch')
|
LOGGER.debug('querying Elasticsearch')
|
||||||
if filterq:
|
if filterq:
|
||||||
LOGGER.debug(f'adding cql object: {filterq.model_dump_json()}')
|
LOGGER.debug(f'adding cql object: {filterq.json()}')
|
||||||
query = update_query(input_query=query, cql=filterq)
|
query = update_query(input_query=query, cql=filterq)
|
||||||
LOGGER.debug(json.dumps(query, indent=4))
|
LOGGER.debug(json.dumps(query, indent=4))
|
||||||
|
|
||||||
@@ -646,16 +647,16 @@ class ESQueryBuilder:
|
|||||||
def _build_query(q, cql):
|
def _build_query(q, cql):
|
||||||
|
|
||||||
# this would be handled by the AST with the traverse of CQL model
|
# this would be handled by the AST with the traverse of CQL model
|
||||||
op, node = get_next_node(cql.root)
|
op, node = get_next_node(cql.__root__)
|
||||||
q.operation = op
|
q.operation = op
|
||||||
if isinstance(node, list):
|
if isinstance(node, list):
|
||||||
query_list = []
|
query_list = []
|
||||||
for elem in node:
|
for elem in node:
|
||||||
op, next_node = get_next_node(elem)
|
op, next_node = get_next_node(elem)
|
||||||
if not getattr(next_node, 'between', 0) == 0:
|
if not getattr(next_node, 'between', 0) == 0:
|
||||||
property = next_node.between.value.root.root.property
|
property = next_node.between.value.__root__.__root__.property
|
||||||
lower = next_node.between.lower.root.root
|
lower = next_node.between.lower.__root__.__root__
|
||||||
upper = next_node.between.upper.root.root
|
upper = next_node.between.upper.__root__.__root__
|
||||||
query_list.append(Q(
|
query_list.append(Q(
|
||||||
{
|
{
|
||||||
'range':
|
'range':
|
||||||
@@ -666,24 +667,24 @@ def _build_query(q, cql):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
if not getattr(next_node, 'root', 0) == 0:
|
if not getattr(next_node, '__root__', 0) == 0:
|
||||||
scalars = tuple(next_node.root.eq.root)
|
scalars = tuple(next_node.__root__.eq.__root__)
|
||||||
property = scalars[0].root.property
|
property = scalars[0].__root__.property
|
||||||
value = scalars[1].root.root
|
value = scalars[1].__root__.__root__
|
||||||
query_list.append(Q(
|
query_list.append(Q(
|
||||||
{'match': {f'{property}': f'{value}'}}
|
{'match': {f'{property}': f'{value}'}}
|
||||||
))
|
))
|
||||||
q.must(query_list)
|
q.must(query_list)
|
||||||
elif not getattr(node, 'between', 0) == 0:
|
elif not getattr(node, 'between', 0) == 0:
|
||||||
property = node.between.value.root.root.property
|
property = node.between.value.__root__.__root__.property
|
||||||
lower = None
|
lower = None
|
||||||
if not getattr(node.between.lower,
|
if not getattr(node.between.lower,
|
||||||
'root', 0) == 0:
|
'__root__', 0) == 0:
|
||||||
lower = node.between.lower.root.root
|
lower = node.between.lower.__root__.__root__
|
||||||
upper = None
|
upper = None
|
||||||
if not getattr(node.between.upper,
|
if not getattr(node.between.upper,
|
||||||
'root', 0) == 0:
|
'__root__', 0) == 0:
|
||||||
upper = node.between.upper.root.root
|
upper = node.between.upper.__root__.__root__
|
||||||
query = Q(
|
query = Q(
|
||||||
{
|
{
|
||||||
'range':
|
'range':
|
||||||
@@ -695,26 +696,26 @@ def _build_query(q, cql):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
q.must(query)
|
q.must(query)
|
||||||
elif not getattr(node, 'root', 0) == 0:
|
elif not getattr(node, '__root__', 0) == 0:
|
||||||
next_op, next_node = get_next_node(node)
|
next_op, next_node = get_next_node(node)
|
||||||
if not getattr(next_node, 'eq', 0) == 0:
|
if not getattr(next_node, 'eq', 0) == 0:
|
||||||
scalars = tuple(next_node.eq.root)
|
scalars = tuple(next_node.eq.__root__)
|
||||||
property = scalars[0].root.property
|
property = scalars[0].__root__.property
|
||||||
value = scalars[1].root.root
|
value = scalars[1].__root__.__root__
|
||||||
query = Q(
|
query = Q(
|
||||||
{'match': {f'{property}': f'{value}'}}
|
{'match': {f'{property}': f'{value}'}}
|
||||||
)
|
)
|
||||||
q.must(query)
|
q.must(query)
|
||||||
elif not getattr(node, 'intersects', 0) == 0:
|
elif not getattr(node, 'intersects', 0) == 0:
|
||||||
property = node.intersects.root[0].root.property
|
property = node.intersects.__root__[0].__root__.property
|
||||||
if property == 'geometry':
|
if property == 'geometry':
|
||||||
geom_type = node.intersects.root[
|
geom_type = node.intersects.__root__[
|
||||||
1].root.root.root.type
|
1].__root__.__root__.__root__.type
|
||||||
if geom_type == 'Polygon':
|
if geom_type == 'Polygon':
|
||||||
coordinates = node.intersects.root[
|
coordinates = node.intersects.__root__[
|
||||||
1].root.root.root.coordinates
|
1].__root__.__root__.__root__.coordinates
|
||||||
coords_list = [
|
coords_list = [
|
||||||
poly_coords.root for poly_coords in coordinates[0]
|
poly_coords.__root__ for poly_coords in coordinates[0]
|
||||||
]
|
]
|
||||||
filter_ = Q(
|
filter_ = Q(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ class MVTTippecanoeProvider(BaseMVTProvider):
|
|||||||
content.tiles = service_url
|
content.tiles = service_url
|
||||||
content.vector_layers = json.loads(
|
content.vector_layers = json.loads(
|
||||||
metadata_json_content["json"])["vector_layers"]
|
metadata_json_content["json"])["vector_layers"]
|
||||||
metadata['metadata'] = content.model_dump()
|
metadata['metadata'] = content.dict()
|
||||||
# Some providers may not implement tilejson metadata
|
# Some providers may not implement tilejson metadata
|
||||||
metadata['tilejson_url'] = f'{metadata_url}?f=tilejson'
|
metadata['tilejson_url'] = f'{metadata_url}?f=tilejson'
|
||||||
except ProviderConnectionError:
|
except ProviderConnectionError:
|
||||||
@@ -357,7 +357,7 @@ class MVTTippecanoeProvider(BaseMVTProvider):
|
|||||||
|
|
||||||
content.links = links
|
content.links = links
|
||||||
|
|
||||||
return content.model_dump(exclude_none=True)
|
return content.dict(exclude_none=True)
|
||||||
|
|
||||||
def get_vendor_metadata(self, dataset, server_url, layer, tileset,
|
def get_vendor_metadata(self, dataset, server_url, layer, tileset,
|
||||||
title, description, keywords, **kwargs):
|
title, description, keywords, **kwargs):
|
||||||
@@ -376,7 +376,7 @@ class MVTTippecanoeProvider(BaseMVTProvider):
|
|||||||
content.tiles = service_url
|
content.tiles = service_url
|
||||||
content.vector_layers = json.loads(
|
content.vector_layers = json.loads(
|
||||||
metadata_json_content["json"])["vector_layers"]
|
metadata_json_content["json"])["vector_layers"]
|
||||||
return content.model_dump()
|
return content.dict()
|
||||||
except ProviderConnectionError:
|
except ProviderConnectionError:
|
||||||
msg = f'No tiles metadata json available: {self.service_metadata_url}' # noqa
|
msg = f'No tiles metadata json available: {self.service_metadata_url}' # noqa
|
||||||
LOGGER.error(msg)
|
LOGGER.error(msg)
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ starlette
|
|||||||
uvicorn[standard]
|
uvicorn[standard]
|
||||||
httpx
|
httpx
|
||||||
|
|
||||||
|
# Pydantic/Dataclasses models
|
||||||
|
polyfactory
|
||||||
|
|
||||||
# PEP8
|
# PEP8
|
||||||
flake8
|
flake8
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
Django
|
Django
|
||||||
pydantic
|
pydantic<2.0
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ filelock
|
|||||||
Flask
|
Flask
|
||||||
jinja2
|
jinja2
|
||||||
jsonschema
|
jsonschema
|
||||||
pydantic
|
pydantic<2.0
|
||||||
pygeofilter
|
pygeofilter
|
||||||
pygeoif
|
pygeoif
|
||||||
pyproj
|
pyproj
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Tom Kralidis
|
# Copyright (c) 2020 Tom Kralidis
|
||||||
# Copyright (c) 2021 Francesco Bartoli
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation
|
# obtaining a copy of this software and associated documentation
|
||||||
@@ -78,7 +78,7 @@ def between():
|
|||||||
"upper": 100000
|
"upper": 100000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CQLModel.model_validate(between_)
|
return CQLModel.parse_obj(between_)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -89,7 +89,7 @@ def between_upper():
|
|||||||
"upper": 100000
|
"upper": 100000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CQLModel.model_validate(between_)
|
return CQLModel.parse_obj(between_)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -100,7 +100,7 @@ def between_lower():
|
|||||||
"lower": 10000
|
"lower": 10000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CQLModel.model_validate(between_)
|
return CQLModel.parse_obj(between_)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -111,7 +111,7 @@ def eq():
|
|||||||
"Admin-0 capital"
|
"Admin-0 capital"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return CQLModel.model_validate(eq_)
|
return CQLModel.parse_obj(eq_)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -135,7 +135,7 @@ def _and(eq, between):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
return CQLModel.model_validate(and_)
|
return CQLModel.parse_obj(and_)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -155,7 +155,7 @@ def intersects():
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
return CQLModel.model_validate(intersects)
|
return CQLModel.parse_obj(intersects)
|
||||||
|
|
||||||
|
|
||||||
def test_query(config):
|
def test_query(config):
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# =================================================================
|
||||||
|
#
|
||||||
|
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Francesco Bartoli
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation
|
||||||
|
# files (the "Software"), to deal in the Software without
|
||||||
|
# restriction, including without limitation the rights to use,
|
||||||
|
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following
|
||||||
|
# conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
from polyfactory.factories.pydantic_factory import ModelFactory
|
||||||
|
from polyfactory.pytest_plugin import register_fixture
|
||||||
|
|
||||||
|
from pygeoapi.models.provider.base import GeospatialDataType
|
||||||
|
from pygeoapi.models.cql import (CQLModel, ComparisonPredicate,
|
||||||
|
ScalarExpression, SpatialPredicate,
|
||||||
|
TemporalPredicate, AndExpression,
|
||||||
|
Between, EqExpression, ScalarOperands,
|
||||||
|
IntersectsExpression, SpatialOperands)
|
||||||
|
|
||||||
|
|
||||||
|
@register_fixture
|
||||||
|
class CQLModelFactory(ModelFactory[CQLModel]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register_fixture
|
||||||
|
class GeospatialDataTypeFactory(ModelFactory[GeospatialDataType]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register_fixture
|
||||||
|
class BetweenModelFactory(ModelFactory[Between]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register_fixture
|
||||||
|
class EqExpressionModelFactory(ModelFactory[EqExpression]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register_fixture
|
||||||
|
class IntersectsExpressionModelFactory(ModelFactory[IntersectsExpression]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def test_cql_model(cql_model_factory: CQLModelFactory) -> None:
|
||||||
|
cql_model_instance = cql_model_factory.build()
|
||||||
|
assert isinstance(cql_model_instance, CQLModel)
|
||||||
|
assert cql_model_instance.dict()
|
||||||
|
assert type(cql_model_instance.__root__) in [
|
||||||
|
ComparisonPredicate, SpatialPredicate, TemporalPredicate, AndExpression
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_provider_base_geospatial_data_type(
|
||||||
|
geospatial_data_type_factory: GeospatialDataTypeFactory) -> None:
|
||||||
|
gdt_instance = geospatial_data_type_factory.build()
|
||||||
|
assert gdt_instance.dict()
|
||||||
|
assert isinstance(gdt_instance, GeospatialDataType)
|
||||||
|
|
||||||
|
|
||||||
|
def test_between_model(between_model_factory: BetweenModelFactory) -> None:
|
||||||
|
between_model_instance = between_model_factory.build()
|
||||||
|
assert isinstance(between_model_instance, Between)
|
||||||
|
assert between_model_instance.dict()
|
||||||
|
assert type(between_model_instance.lower) is ScalarExpression
|
||||||
|
assert type(between_model_instance.upper) is ScalarExpression
|
||||||
|
|
||||||
|
|
||||||
|
def test_eq_expression_model(
|
||||||
|
eq_expression_model_factory: EqExpressionModelFactory) -> None:
|
||||||
|
eqexpr_model_instance = eq_expression_model_factory.build()
|
||||||
|
assert isinstance(eqexpr_model_instance, EqExpression)
|
||||||
|
assert eqexpr_model_instance.dict()
|
||||||
|
assert type(eqexpr_model_instance.eq) is ScalarOperands
|
||||||
|
|
||||||
|
|
||||||
|
def test_intersects_expression_model(
|
||||||
|
intersects_expression_model_factory: IntersectsExpressionModelFactory) -> None: # noqa
|
||||||
|
intersectsexpr_model_instance = intersects_expression_model_factory.build()
|
||||||
|
assert isinstance(intersectsexpr_model_instance, IntersectsExpression)
|
||||||
|
assert intersectsexpr_model_instance.dict()
|
||||||
|
assert type(intersectsexpr_model_instance.intersects) is SpatialOperands
|
||||||
Reference in New Issue
Block a user