From: Landry Breuil Subject: Re: [wip] devel/py-pydantic 2.8.2 devel/py-pydantic-core-2.21.0 To: ports@openbsd.org Date: Mon, 12 Aug 2024 15:57:28 +0200 Le Mon, Aug 12, 2024 at 03:19:28PM +0200, Renaud Allard a écrit : > > > On 8/12/24 3:05 PM, Renaud Allard wrote: > > Hello, > > > > Here is a WIP for devel/py-pydantic 2.8.2  devel/py-pydantic-core-2.21.0 > > > > It will more than likely break geo/pygeoapi unless this patch is > > applied: https://github.com/geopython/pygeoapi/pull/1353/files > > > > But it should "unbreak" net/synapse. > > > > It's all untested ATM. > > > > Any comments? > > > > Best Regards > > Sorry, I had forgotten to "CVS rm" the patches. > -MODPY_PYBUILD = setuptools > +MODPY_PYBUILD = hatchling > > -BUILD_DEPENDS = lang/cython${MODPY_FLAVOR} > -RUN_DEPENDS = devel/py-typing-extensions${MODPY_FLAVOR} > +BUILD_DEPENDS = devel/py-hatchling${MODPY_FLAVOR} \ there's no need for hatchling in BDEP if its used in PYBUILD. i wont make comments on mixed python/rust ports, but with the attached diff the pygeoapi command doesnt blow upon startup. you also have to check py-pydantic-compat and py-inflect. Landry ? patch-pygeoapi_util_py ? files/pygeoapi-config.yml Index: Makefile =================================================================== RCS file: /cvs/ports/geo/pygeoapi/Makefile,v diff -u -r1.25 Makefile --- Makefile 29 Jul 2024 06:46:22 -0000 1.25 +++ Makefile 12 Aug 2024 13:56:34 -0000 @@ -2,6 +2,7 @@ MODPY_EGG_VERSION = 0.17.0 DISTNAME = pygeoapi-${MODPY_EGG_VERSION} +REVISION = 0 CATEGORIES = geo devel @@ -23,6 +24,7 @@ devel/py-dateutil${MODPY_FLAVOR} \ devel/py-jsonschema${MODPY_FLAVOR} \ devel/py-pydantic${MODPY_FLAVOR} \ + devel/py-typing-extensions${MODPY_FLAVOR} \ devel/py-tz${MODPY_FLAVOR} \ geo/mapserver,-python \ geo/py-geofilter${MODPY_FLAVOR} \ Index: patches/patch-pygeoapi_models_config_py =================================================================== RCS file: patches/patch-pygeoapi_models_config_py diff -N patches/patch-pygeoapi_models_config_py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-pygeoapi_models_config_py 12 Aug 2024 13:56:34 -0000 @@ -0,0 +1,28 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: pygeoapi/models/config.py +--- pygeoapi/models/config.py.orig ++++ pygeoapi/models/config.py +@@ -36,7 +36,7 @@ from pydantic import BaseModel, Field + + class APIRules(BaseModel): + """ Pydantic model for API design rules that must be adhered to. """ +- api_version: str = Field(regex=r'^\d+\.\d+\..+$', ++ api_version: str = Field(pattern=r'^\d+\.\d+\..+$', + description="Semantic API version number.") + url_prefix: str = Field( + "", +@@ -62,11 +62,11 @@ class APIRules(BaseModel): + """ Returns a new APIRules instance for the current API version + and configured rules. """ + obj = { +- k: v for k, v in rules_config.items() if k in APIRules.__fields__ ++ k: v for k, v in rules_config.items() if k in APIRules.model_fields + } + # Validation will fail if required `api_version` is missing + # or if `api_version` is not a semantic version number +- return APIRules.parse_obj(obj) ++ return APIRules.model_validate(obj) + + @property + def response_headers(self) -> dict: Index: patches/patch-pygeoapi_models_cql_py =================================================================== RCS file: patches/patch-pygeoapi_models_cql_py diff -N patches/patch-pygeoapi_models_cql_py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-pygeoapi_models_cql_py 12 Aug 2024 13:56:35 -0000 @@ -0,0 +1,650 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: pygeoapi/models/cql.py +--- pygeoapi/models/cql.py.orig ++++ pygeoapi/models/cql.py +@@ -35,234 +35,235 @@ + from datetime import date, datetime + from typing import Any, List, Literal, Optional, Union + +-from pydantic import BaseModel, Field ++from pydantic import RootModel, Field ++from typing_extensions import Literal + + +-class CQLModel(BaseModel): +- __root__: 'Union[\n ComparisonPredicate,\n SpatialPredicate,\n TemporalPredicate,\n AndExpression\n ]' ++class CQLModel(RootModel): ++ root: 'Union[\n ComparisonPredicate,\n SpatialPredicate,\n TemporalPredicate,\n AndExpression\n ]' + + +-class AndExpression(BaseModel): ++class AndExpression(RootModel): + and_: 'List[ComparisonPredicate]' = Field(..., alias='and') + + +-class NotExpression(BaseModel): ++class NotExpression(RootModel): + not_: 'List[Any]' = Field(..., alias='not') + + +-class OrExpression(BaseModel): ++class OrExpression(RootModel): + or_: 'List[Any]' = Field(..., alias='or') + + +-class PropertyRef(BaseModel): ++class PropertyRef(RootModel): + property: 'Optional[str]' = None + + +-class ScalarLiteral(BaseModel): +- __root__: 'Union[str, float, bool]' ++class ScalarLiteral(RootModel): ++ root: 'Union[str, float, bool]' + + +-class Bbox(BaseModel): +- __root__: 'List[float]' ++class Bbox(RootModel): ++ root: 'List[float]' + + +-class LinestringCoordinate(BaseModel): +- __root__: 'List[Any]' ++class LinestringCoordinate(RootModel): ++ root: 'List[Any]' + + +-class Linestring(BaseModel): ++class Linestring(RootModel): + type: Literal['LineString'] + coordinates: 'List[LinestringCoordinate]' = Field(...) + bbox: 'Optional[List[float]]' = Field(None) + + +-class MultilineStringCoordinate(BaseModel): +- __root__: 'List[Any]' ++class MultilineStringCoordinate(RootModel): ++ root: 'List[Any]' + + +-class Multilinestring(BaseModel): ++class Multilinestring(RootModel): + type: Literal['MultiLineString'] + coordinates: 'List[List[MultilineStringCoordinate]]' + bbox: 'Optional[List[float]]' = Field(None) + + +-class Multipoint(BaseModel): ++class Multipoint(RootModel): + type: Literal['MultiPoint'] + coordinates: 'List[List[float]]' + bbox: 'Optional[List[float]]' = Field(None) + + +-class MultipolygonCoordinateItem(BaseModel): +- __root__: 'List[Any]' ++class MultipolygonCoordinateItem(RootModel): ++ root: 'List[Any]' + + +-class Multipolygon(BaseModel): ++class Multipolygon(RootModel): + type: Literal['MultiPolygon'] + coordinates: 'List[List[List[MultipolygonCoordinateItem]]]' + bbox: 'Optional[List[float]]' = Field(None) + + +-class Point(BaseModel): ++class Point(RootModel): + type: Literal['Point'] + coordinates: 'List[float]' = Field(...) + bbox: 'Optional[List[float]]' = Field(None) + + +-class PolygonCoordinatesItem(BaseModel): +- __root__: 'List[Any]' ++class PolygonCoordinatesItem(RootModel): ++ root: 'List[Any]' + + +-class Polygon(BaseModel): ++class Polygon(RootModel): + type: Literal['Polygon'] + coordinates: 'List[List[PolygonCoordinatesItem]]' + bbox: 'Optional[List[float]]' = Field(None) + + +-class TimeString(BaseModel): +- __root__: 'Union[date, datetime]' ++class TimeString(RootModel): ++ root: 'Union[date, datetime]' + + +-class EnvelopeLiteral(BaseModel): ++class EnvelopeLiteral(RootModel): + bbox: 'Bbox' + + +-class GeometryLiteral(BaseModel): +- __root__: 'Union[\n Point,\n Linestring,\n Polygon,\n Multipoint,\n Multilinestring,\n Multipolygon\n ]' ++class GeometryLiteral(RootModel): ++ root: 'Union[\n Point,\n Linestring,\n Polygon,\n Multipoint,\n Multilinestring,\n Multipolygon\n ]' + + +-class TypedTimeString(BaseModel): ++class TypedTimeString(RootModel): + datetime: 'TimeString' + + +-class PeriodString(BaseModel): +- __root__: 'List[Union[TimeString, str]]' = Field(...) ++class PeriodString(RootModel): ++ root: 'List[Union[TimeString, str]]' = Field(...) + + +-class SpatialLiteral(BaseModel): +- __root__: 'Union[GeometryLiteral, EnvelopeLiteral]' ++class SpatialLiteral(RootModel): ++ root: 'Union[GeometryLiteral, EnvelopeLiteral]' + + +-class TemporalLiteral(BaseModel): +- __root__: 'Union[TimeString, PeriodString]' ++class TemporalLiteral(RootModel): ++ root: 'Union[TimeString, PeriodString]' + + +-class TypedPeriodString(BaseModel): ++class TypedPeriodString(RootModel): + datetime: 'PeriodString' + + +-class TypedTemporalLiteral(BaseModel): +- __root__: 'Union[TypedTimeString, TypedPeriodString]' ++class TypedTemporalLiteral(RootModel): ++ root: 'Union[TypedTimeString, TypedPeriodString]' + + +-class ArrayPredicate(BaseModel): +- __root__: 'Union[\n AequalsExpression,\n AcontainsExpression,\n AcontainedByExpression,\n AoverlapsExpression,\n ]' ++class ArrayPredicate(RootModel): ++ root: 'Union[\n AequalsExpression,\n AcontainsExpression,\n AcontainedByExpression,\n AoverlapsExpression,\n ]' + + +-class ComparisonPredicate(BaseModel): +- __root__: 'Union[\n BinaryComparisonPredicate,\n IsLikePredicate,\n IsBetweenPredicate,\n IsInListPredicate,\n IsNullPredicate,\n ]' ++class ComparisonPredicate(RootModel): ++ root: 'Union[\n BinaryComparisonPredicate,\n IsLikePredicate,\n IsBetweenPredicate,\n IsInListPredicate,\n IsNullPredicate,\n ]' + + +-class SpatialPredicate(BaseModel): +- __root__: 'Union[\n IntersectsExpression,\n EqualsExpression,\n DisjointExpression,\n TouchesExpression,\n WithinExpression,\n OverlapsExpression,\n CrossesExpression,\n ContainsExpression,\n ]' ++class SpatialPredicate(RootModel): ++ root: 'Union[\n IntersectsExpression,\n EqualsExpression,\n DisjointExpression,\n TouchesExpression,\n WithinExpression,\n OverlapsExpression,\n CrossesExpression,\n ContainsExpression,\n ]' + + +-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 ]' ++class TemporalPredicate(RootModel): ++ 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(RootModel): + acontainedBy: 'ArrayExpression' + + +-class AcontainsExpression(BaseModel): ++class AcontainsExpression(RootModel): + acontains: 'ArrayExpression' + + +-class AequalsExpression(BaseModel): ++class AequalsExpression(RootModel): + aequals: 'ArrayExpression' + + +-class AfterExpression(BaseModel): ++class AfterExpression(RootModel): + after: 'TemporalOperands' + + +-class AnyinteractsExpression(BaseModel): ++class AnyinteractsExpression(RootModel): + anyinteracts: 'TemporalOperands' + + +-class AoverlapsExpression(BaseModel): ++class AoverlapsExpression(RootModel): + aoverlaps: 'ArrayExpression' + + +-class BeforeExpression(BaseModel): ++class BeforeExpression(RootModel): + before: 'TemporalOperands' + + +-class BeginsExpression(BaseModel): ++class BeginsExpression(RootModel): + begins: 'TemporalOperands' + + +-class BegunbyExpression(BaseModel): ++class BegunbyExpression(RootModel): + begunby: 'TemporalOperands' + + +-class BinaryComparisonPredicate(BaseModel): +- __root__: 'Union[\n EqExpression, LtExpression, GtExpression, LteExpression, GteExpression\n ]' ++class BinaryComparisonPredicate(RootModel): ++ root: 'Union[\n EqExpression, LtExpression, GtExpression, LteExpression, GteExpression\n ]' + + +-class ContainsExpression(BaseModel): ++class ContainsExpression(RootModel): + contains: 'SpatialOperands' + + +-class CrossesExpression(BaseModel): ++class CrossesExpression(RootModel): + crosses: 'SpatialOperands' + + +-class DisjointExpression(BaseModel): ++class DisjointExpression(RootModel): + disjoint: 'SpatialOperands' + + +-class DuringExpression(BaseModel): ++class DuringExpression(RootModel): + during: 'TemporalOperands' + + +-class EndedbyExpression(BaseModel): ++class EndedbyExpression(RootModel): + endedby: 'TemporalOperands' + + +-class EndsExpression(BaseModel): ++class EndsExpression(RootModel): + ends: 'TemporalOperands' + + +-class EqualsExpression(BaseModel): ++class EqualsExpression(RootModel): + equals: 'SpatialOperands' + + +-class IntersectsExpression(BaseModel): ++class IntersectsExpression(RootModel): + intersects: 'SpatialOperands' + + +-class Between(BaseModel): ++class Between(RootModel): + value: 'ValueExpression' +- lower: 'ScalarExpression' = Field(None) +- upper: 'ScalarExpression' = Field(None) ++ lower: 'Optional[ScalarExpression]' = Field(None) ++ upper: 'Optional[ScalarExpression]' = Field(None) + + +-class IsBetweenPredicate(BaseModel): ++class IsBetweenPredicate(RootModel): + between: 'Between' + + +-class In(BaseModel): ++class In(RootModel): + value: 'ValueExpression' + list: 'List[ValueExpression]' + nocase: 'Optional[bool]' = True + + +-class IsInListPredicate(BaseModel): ++class IsInListPredicate(RootModel): + in_: 'In' = Field(..., alias='in') + + +-class IsLikePredicate(BaseModel): ++class IsLikePredicate(RootModel): + like: 'ScalarOperands' + wildcard: 'Optional[str]' = '%' + singleChar: 'Optional[str]' = '.' +@@ -270,200 +271,200 @@ class IsLikePredicate(BaseModel): + nocase: 'Optional[bool]' = True + + +-class IsNullPredicate(BaseModel): ++class IsNullPredicate(RootModel): + isNull: 'ScalarExpression' + + +-class MeetsExpression(BaseModel): ++class MeetsExpression(RootModel): + meets: 'TemporalOperands' + + +-class MetbyExpression(BaseModel): ++class MetbyExpression(RootModel): + metby: 'TemporalOperands' + + +-class OverlappedbyExpression(BaseModel): ++class OverlappedbyExpression(RootModel): + overlappedby: 'TemporalOperands' + + +-class OverlapsExpression(BaseModel): ++class OverlapsExpression(RootModel): + overlaps: 'SpatialOperands' + + +-class TcontainsExpression(BaseModel): ++class TcontainsExpression(RootModel): + tcontains: 'TemporalOperands' + + +-class TequalsExpression(BaseModel): ++class TequalsExpression(RootModel): + tequals: 'TemporalOperands' + + +-class TouchesExpression(BaseModel): ++class TouchesExpression(RootModel): + touches: 'SpatialOperands' + + +-class ToverlapsExpression(BaseModel): ++class ToverlapsExpression(RootModel): + toverlaps: 'TemporalOperands' + + +-class WithinExpression(BaseModel): ++class WithinExpression(RootModel): + within: 'SpatialOperands' + + +-class ArrayExpression(BaseModel): +- __root__: 'List[Union[PropertyRef, FunctionRef, ArrayLiteral]]' = Field( ++class ArrayExpression(RootModel): ++ root: 'List[Union[PropertyRef, FunctionRef, ArrayLiteral]]' = Field( + ... # , max_items=2, min_items=2 + ) + + +-class EqExpression(BaseModel): ++class EqExpression(RootModel): + eq: 'ScalarOperands' + + +-class GtExpression(BaseModel): ++class GtExpression(RootModel): + gt: 'ScalarOperands' + + +-class GteExpression(BaseModel): ++class GteExpression(RootModel): + gte: 'ScalarOperands' + + +-class LtExpression(BaseModel): ++class LtExpression(RootModel): + lt: 'ScalarOperands' + + +-class LteExpression(BaseModel): ++class LteExpression(RootModel): + lte: 'ScalarOperands' + + +-class ScalarExpression(BaseModel): +- __root__: 'Union[ScalarLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression]' ++class ScalarExpression(RootModel): ++ root: 'Union[ScalarLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression]' + + +-class ScalarOperands(BaseModel): +- __root__: 'List[ScalarExpression]' = Field(...) ++class ScalarOperands(RootModel): ++ root: 'List[ScalarExpression]' = Field(...) + + +-class SpatialOperands(BaseModel): +- __root__: 'List[GeomExpression]' = Field(...) ++class SpatialOperands(RootModel): ++ root: 'List[GeomExpression]' = Field(...) + + +-class TemporalOperands(BaseModel): +- __root__: 'List[TemporalExpression]' = Field(...) ++class TemporalOperands(RootModel): ++ root: 'List[TemporalExpression]' = Field(...) + # , max_items=2, min_items=2) + + +-class ValueExpression(BaseModel): +- __root__: 'Union[ScalarExpression, SpatialLiteral, TypedTemporalLiteral]' ++class ValueExpression(RootModel): ++ root: 'Union[ScalarExpression, SpatialLiteral, TypedTemporalLiteral]' + + +-class ArithmeticExpression(BaseModel): +- __root__: 'Union[AddExpression, SubExpression, MulExpression, DivExpression]' ++class ArithmeticExpression(RootModel): ++ root: 'Union[AddExpression, SubExpression, MulExpression, DivExpression]' + + +-class ArrayLiteral(BaseModel): +- __root__: 'List[\n Union[\n ScalarLiteral,\n SpatialLiteral,\n TypedTemporalLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression,\n ArrayLiteral,\n ]\n ]' ++class ArrayLiteral(RootModel): ++ 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(RootModel): + function: 'Function' + + +-class GeomExpression(BaseModel): +- __root__: 'Union[SpatialLiteral, PropertyRef, FunctionRef]' ++class GeomExpression(RootModel): ++ root: 'Union[SpatialLiteral, PropertyRef, FunctionRef]' + + +-class TemporalExpression(BaseModel): +- __root__: 'Union[TemporalLiteral, PropertyRef, FunctionRef]' ++class TemporalExpression(RootModel): ++ root: 'Union[TemporalLiteral, PropertyRef, FunctionRef]' + + + # here +-class AddExpression(BaseModel): ++class AddExpression(RootModel): + add_: 'ArithmeticOperands' = Field(..., alias='+') + + + # here +-class DivExpression(BaseModel): ++class DivExpression(RootModel): + div_: 'ArithmeticOperands' = Field(None, alias='/') + + +-class Function(BaseModel): ++class Function(RootModel): + name: 'str' + arguments: 'Optional[\n List[\n Union[\n ScalarLiteral,\n SpatialLiteral,\n TypedTemporalLiteral,\n PropertyRef,\n FunctionRef,\n ArithmeticExpression,\n ArrayLiteral,\n ]\n ]\n ]' = None + + + # here +-class MulExpression(BaseModel): ++class MulExpression(RootModel): + mul_: 'ArithmeticOperands' = Field(..., alias='*') + + + # here +-class SubExpression(BaseModel): ++class SubExpression(RootModel): + sub_: 'ArithmeticOperands' = Field(..., alias='-') + + +-class ArithmeticOperands(BaseModel): +- __root__: 'List[\n Union[ArithmeticExpression, PropertyRef, FunctionRef, float]\n ]' = Field(...) ++class ArithmeticOperands(RootModel): ++ root: 'List[\n Union[ArithmeticExpression, PropertyRef, FunctionRef, float]\n ]' = Field(...) + + +-CQLModel.update_forward_refs() +-AndExpression.update_forward_refs() +-ArrayPredicate.update_forward_refs() +-ComparisonPredicate.update_forward_refs() +-SpatialPredicate.update_forward_refs() +-TemporalPredicate.update_forward_refs() +-AcontainedByExpression.update_forward_refs() +-AcontainsExpression.update_forward_refs() +-AequalsExpression.update_forward_refs() +-AfterExpression.update_forward_refs() +-AnyinteractsExpression.update_forward_refs() +-AoverlapsExpression.update_forward_refs() +-BeforeExpression.update_forward_refs() +-BeginsExpression.update_forward_refs() +-BegunbyExpression.update_forward_refs() +-BinaryComparisonPredicate.update_forward_refs() +-ContainsExpression.update_forward_refs() +-CrossesExpression.update_forward_refs() +-DisjointExpression.update_forward_refs() +-DuringExpression.update_forward_refs() +-EndedbyExpression.update_forward_refs() +-EndsExpression.update_forward_refs() +-EqualsExpression.update_forward_refs() +-IntersectsExpression.update_forward_refs() +-Between.update_forward_refs() +-In.update_forward_refs() +-IsBetweenPredicate.update_forward_refs() +-IsLikePredicate.update_forward_refs() +-IsNullPredicate.update_forward_refs() +-ValueExpression.update_forward_refs() +-MeetsExpression.update_forward_refs() +-MetbyExpression.update_forward_refs() +-OverlappedbyExpression.update_forward_refs() +-OverlapsExpression.update_forward_refs() +-TcontainsExpression.update_forward_refs() +-TequalsExpression.update_forward_refs() +-TouchesExpression.update_forward_refs() +-ToverlapsExpression.update_forward_refs() +-WithinExpression.update_forward_refs() +-ArrayExpression.update_forward_refs() +-EqExpression.update_forward_refs() +-GtExpression.update_forward_refs() +-GteExpression.update_forward_refs() +-LtExpression.update_forward_refs() +-LteExpression.update_forward_refs() +-ScalarExpression.update_forward_refs() +-ScalarOperands.update_forward_refs() +-SpatialOperands.update_forward_refs() +-TemporalOperands.update_forward_refs() +-ArithmeticExpression.update_forward_refs() +-ArrayLiteral.update_forward_refs() +-ScalarLiteral.update_forward_refs() +-PropertyRef.update_forward_refs() +-FunctionRef.update_forward_refs() +-AddExpression.update_forward_refs() +-DivExpression.update_forward_refs() +-MulExpression.update_forward_refs() +-SubExpression.update_forward_refs() ++CQLModel.model_rebuild() ++AndExpression.model_rebuild() ++ArrayPredicate.model_rebuild() ++ComparisonPredicate.model_rebuild() ++SpatialPredicate.model_rebuild() ++TemporalPredicate.model_rebuild() ++AcontainedByExpression.model_rebuild() ++AcontainsExpression.model_rebuild() ++AequalsExpression.model_rebuild() ++AfterExpression.model_rebuild() ++AnyinteractsExpression.model_rebuild() ++AoverlapsExpression.model_rebuild() ++BeforeExpression.model_rebuild() ++BeginsExpression.model_rebuild() ++BegunbyExpression.model_rebuild() ++BinaryComparisonPredicate.model_rebuild() ++ContainsExpression.model_rebuild() ++CrossesExpression.model_rebuild() ++DisjointExpression.model_rebuild() ++DuringExpression.model_rebuild() ++EndedbyExpression.model_rebuild() ++EndsExpression.model_rebuild() ++EqualsExpression.model_rebuild() ++IntersectsExpression.model_rebuild() ++Between.model_rebuild() ++In.model_rebuild() ++IsBetweenPredicate.model_rebuild() ++IsLikePredicate.model_rebuild() ++IsNullPredicate.model_rebuild() ++ValueExpression.model_rebuild() ++MeetsExpression.model_rebuild() ++MetbyExpression.model_rebuild() ++OverlappedbyExpression.model_rebuild() ++OverlapsExpression.model_rebuild() ++TcontainsExpression.model_rebuild() ++TequalsExpression.model_rebuild() ++TouchesExpression.model_rebuild() ++ToverlapsExpression.model_rebuild() ++WithinExpression.model_rebuild() ++ArrayExpression.model_rebuild() ++EqExpression.model_rebuild() ++GtExpression.model_rebuild() ++GteExpression.model_rebuild() ++LtExpression.model_rebuild() ++LteExpression.model_rebuild() ++ScalarExpression.model_rebuild() ++ScalarOperands.model_rebuild() ++SpatialOperands.model_rebuild() ++TemporalOperands.model_rebuild() ++ArithmeticExpression.model_rebuild() ++ArrayLiteral.model_rebuild() ++ScalarLiteral.model_rebuild() ++PropertyRef.model_rebuild() ++FunctionRef.model_rebuild() ++AddExpression.model_rebuild() ++DivExpression.model_rebuild() ++MulExpression.model_rebuild() ++SubExpression.model_rebuild() + + + def get_next_node(obj): +@@ -478,25 +479,25 @@ def get_next_node(obj): + next_node = obj.not_ + logical_op = 'not' + elif obj.__repr_name__() == 'ComparisonPredicate': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'SpatialPredicate': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'TemporalPredicate': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'IsBetweenPredicate': + next_node = obj.between + elif obj.__repr_name__() == 'Between': + next_node = obj.value + 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': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'ScalarLiteral': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'PropertyRef': + next_node = obj.property + elif obj.__repr_name__() == 'BinaryComparisonPredicate': +- next_node = obj.__root__ ++ next_node = obj.root + elif obj.__repr_name__() == 'EqExpression': + next_node = obj.eq + logical_op = 'eq' Index: patches/patch-pygeoapi_models_openapi_py =================================================================== RCS file: patches/patch-pygeoapi_models_openapi_py diff -N patches/patch-pygeoapi_models_openapi_py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-pygeoapi_models_openapi_py 12 Aug 2024 13:56:35 -0000 @@ -0,0 +1,22 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: pygeoapi/models/openapi.py +--- pygeoapi/models/openapi.py.orig ++++ pygeoapi/models/openapi.py +@@ -31,7 +31,7 @@ + + from enum import Enum + +-from pydantic import BaseModel ++from pydantic import RootModel + + + class SupportedFormats(Enum): +@@ -39,5 +39,5 @@ class SupportedFormats(Enum): + YAML = "yaml" + + +-class OAPIFormat(BaseModel): +- __root__: SupportedFormats = SupportedFormats.YAML ++class OAPIFormat(RootModel): ++ root: SupportedFormats = SupportedFormats.YAML Index: patches/patch-pygeoapi_provider_elasticsearch__py =================================================================== RCS file: patches/patch-pygeoapi_provider_elasticsearch__py diff -N patches/patch-pygeoapi_provider_elasticsearch__py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-pygeoapi_provider_elasticsearch__py 12 Aug 2024 13:56:35 -0000 @@ -0,0 +1,106 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: pygeoapi/provider/elasticsearch_.py +--- pygeoapi/provider/elasticsearch_.py.orig ++++ pygeoapi/provider/elasticsearch_.py +@@ -295,7 +295,7 @@ class ElasticsearchProvider(BaseProvider): + try: + LOGGER.debug('querying Elasticsearch') + if filterq: +- LOGGER.debug(f'adding cql object: {filterq.json()}') ++ LOGGER.debug(f'adding cql object: {filterq.model_dump_json()}') + query = update_query(input_query=query, cql=filterq) + LOGGER.debug(json.dumps(query, indent=4)) + +@@ -647,16 +647,16 @@ class ESQueryBuilder: + def _build_query(q, cql): + + # 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 + if isinstance(node, list): + query_list = [] + for elem in node: + op, next_node = get_next_node(elem) + if not getattr(next_node, 'between', 0) == 0: +- property = next_node.between.value.__root__.__root__.property +- lower = next_node.between.lower.__root__.__root__ +- upper = next_node.between.upper.__root__.__root__ ++ property = next_node.between.value.root.root.property ++ lower = next_node.between.lower.root.root ++ upper = next_node.between.upper.root.root + query_list.append(Q( + { + 'range': +@@ -667,24 +667,24 @@ def _build_query(q, cql): + } + } + )) +- if not getattr(next_node, '__root__', 0) == 0: +- scalars = tuple(next_node.__root__.eq.__root__) +- property = scalars[0].__root__.property +- value = scalars[1].__root__.__root__ ++ if not getattr(next_node, 'root', 0) == 0: ++ scalars = tuple(next_node.root.eq.root) ++ property = scalars[0].root.property ++ value = scalars[1].root.root + query_list.append(Q( + {'match': {f'{property}': f'{value}'}} + )) + q.must(query_list) + elif not getattr(node, 'between', 0) == 0: +- property = node.between.value.__root__.__root__.property ++ property = node.between.value.root.root.property + lower = None + if not getattr(node.between.lower, +- '__root__', 0) == 0: +- lower = node.between.lower.__root__.__root__ ++ 'root', 0) == 0: ++ lower = node.between.lower.root.root + upper = None + if not getattr(node.between.upper, +- '__root__', 0) == 0: +- upper = node.between.upper.__root__.__root__ ++ 'root', 0) == 0: ++ upper = node.between.upper.root.root + query = Q( + { + 'range': +@@ -696,26 +696,26 @@ def _build_query(q, cql): + } + ) + 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) + if not getattr(next_node, 'eq', 0) == 0: +- scalars = tuple(next_node.eq.__root__) +- property = scalars[0].__root__.property +- value = scalars[1].__root__.__root__ ++ scalars = tuple(next_node.eq.root) ++ property = scalars[0].root.property ++ value = scalars[1].root.root + query = Q( + {'match': {f'{property}': f'{value}'}} + ) + q.must(query) + elif not getattr(node, 'intersects', 0) == 0: +- property = node.intersects.__root__[0].__root__.property ++ property = node.intersects.root[0].root.property + if property == 'geometry': +- geom_type = node.intersects.__root__[ +- 1].__root__.__root__.__root__.type ++ geom_type = node.intersects.root[ ++ 1].root.root.root.type + if geom_type == 'Polygon': +- coordinates = node.intersects.__root__[ +- 1].__root__.__root__.__root__.coordinates ++ coordinates = node.intersects.root[ ++ 1].root.root.root.coordinates + coords_list = [ +- poly_coords.__root__ for poly_coords in coordinates[0] ++ poly_coords.root for poly_coords in coordinates[0] + ] + filter_ = Q( + { Index: patches/patch-requirements_txt =================================================================== RCS file: patches/patch-requirements_txt diff -N patches/patch-requirements_txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-requirements_txt 12 Aug 2024 13:56:35 -0000 @@ -0,0 +1,20 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: requirements.txt +--- requirements.txt.orig ++++ requirements.txt +@@ -4,7 +4,7 @@ filelock + Flask + jinja2 + jsonschema +-pydantic<2.0 ++pydantic + pygeofilter + pygeoif + pyproj +@@ -16,4 +16,5 @@ requests + shapely + SQLAlchemy<2.0.0 + tinydb ++typing-extensions + unicodecsv Index: patches/patch-tests_test_elasticsearch__provider_py =================================================================== RCS file: patches/patch-tests_test_elasticsearch__provider_py diff -N patches/patch-tests_test_elasticsearch__provider_py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-tests_test_elasticsearch__provider_py 12 Aug 2024 13:56:35 -0000 @@ -0,0 +1,59 @@ +https://github.com/geopython/pygeoapi/pull/1353 + +Index: tests/test_elasticsearch__provider.py +--- tests/test_elasticsearch__provider.py.orig ++++ tests/test_elasticsearch__provider.py +@@ -78,7 +78,7 @@ def between(): + "upper": 100000 + } + } +- return CQLModel.parse_obj(between_) ++ return CQLModel.model_validate(between_) + + + @pytest.fixture() +@@ -89,7 +89,7 @@ def between_upper(): + "upper": 100000 + } + } +- return CQLModel.parse_obj(between_) ++ return CQLModel.model_validate(between_) + + + @pytest.fixture() +@@ -100,7 +100,7 @@ def between_lower(): + "lower": 10000 + } + } +- return CQLModel.parse_obj(between_) ++ return CQLModel.model_validate(between_) + + + @pytest.fixture() +@@ -111,7 +111,7 @@ def eq(): + "Admin-0 capital" + ] + } +- return CQLModel.parse_obj(eq_) ++ return CQLModel.model_validate(eq_) + + + @pytest.fixture() +@@ -135,7 +135,7 @@ def _and(eq, between): + } + ] + } +- return CQLModel.parse_obj(and_) ++ return CQLModel.model_validate(and_) + + + @pytest.fixture() +@@ -155,7 +155,7 @@ def intersects(): + ] + } + ]} +- return CQLModel.parse_obj(intersects) ++ return CQLModel.model_validate(intersects) + + + def test_query(config):