Index | Thread | Search

From:
Landry Breuil <landry@openbsd.org>
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

Download raw body.

Thread
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):