Skip to content

Commit

Permalink
Switch bach to StrictStr for Character Literal.
Browse files Browse the repository at this point in the history
  • Loading branch information
eseglem committed Jan 9, 2024
1 parent b3f81d7 commit 204c0b9
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ In addition to this, [HypoFuzz](https://hypofuzz.com/) was used to run coverage

Support will be added for cql2-json later. There are additional custom strategies which will be necessary.

Note: Python 3.9 is the minimum for testing with Hypothesis and HypoFuzz.

## CQL2 Spec

Writing this parser has resulted in feedback and contributions to the [ogcapi-features](https://github.com/opengeospatial/ogcapi-features) CQL2 spec:
Expand Down
78 changes: 49 additions & 29 deletions pycql2/cql2_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@

from datetime import date, datetime
from enum import Enum
from typing import TYPE_CHECKING, List, Literal, MutableSequence, Sequence, Tuple, Union
from typing import (
TYPE_CHECKING,
Any,
List,
Literal,
MutableSequence,
Sequence,
Tuple,
Union,
)

from geojson_pydantic.geometries import Geometry, GeometryCollection
from geojson_pydantic.types import BBox
from pydantic import (
BaseModel,
Field,
RootModel,
Strict,
StrictBool,
StrictFloat,
StrictInt,
Expand All @@ -37,15 +45,6 @@ def join_list(items: Sequence, sep: str) -> str:
return sep.join(str(item) for item in items)


# It would be nice to do something like `CharacterLiteral(str)`, but that causes
# other issues. This seems like the best solution for the time being.
class CharacterLiteral(RootModel):
root: Annotated[str, Strict()]

def __str__(self) -> str:
return make_char_literal(self.root)


class NotExpression(BaseModel):
op: Literal["not"]
args: Tuple[BooleanExpression]
Expand Down Expand Up @@ -278,33 +277,33 @@ def __str__(self) -> str:
return f"INTERVAL({self.interval[0]}, {self.interval[1]})"


class _Casei(BaseModel):
class Casei(BaseModel):
casei: Union[CharacterExpression, PatternExpression]

def __str__(self) -> str:
return f"CASEI({self.casei})"


class CaseiCharacterExpression(_Casei):
class CaseiCharacterExpression(Casei):
casei: CharacterExpression


class CaseiPatternExpression(_Casei):
class CaseiPatternExpression(Casei):
casei: PatternExpression


class _Accenti(BaseModel):
class Accenti(BaseModel):
accenti: Union[CharacterExpression, PatternExpression]

def __str__(self) -> str:
return f"ACCENTI({self.accenti})"


class AccentiCharacterExpression(_Accenti):
class AccentiCharacterExpression(Accenti):
accenti: CharacterExpression


class AccentiPatternExpression(_Accenti):
class AccentiPatternExpression(Accenti):
accenti: PatternExpression


Expand All @@ -315,16 +314,25 @@ def __str__(self) -> str:
return self.root.wkt


CharacterClause = Union[
CaseiCharacterExpression,
AccentiCharacterExpression,
CharacterLiteral,
]
CharacterExpression = Union[
CharacterClause,
PropertyRef,
FunctionRef,
]
class CharLiteralRootModel(RootModel):
root: Any

def __str__(self) -> str:
# If it is already a string, make it a char literal
if isinstance(self.root, str):
return make_char_literal(self.root)
# Otherwise, return the string representation of the root
return str(self.root)


class CharacterClause(CharLiteralRootModel):
root: CharacterClauseItems


class PatternExpression(CharLiteralRootModel):
root: PatternExpressionItems


ComparisonPredicate = Union[
BinaryComparisonPredicate,
IsLikePredicate,
Expand All @@ -348,8 +356,18 @@ def __str__(self) -> str:
ArithmeticExpression, PropertyRef, FunctionRef, StrictFloatOrInt
]
ArrayExpressionItems = Union[Array, PropertyRef, FunctionRef]
PatternExpression = Union[
CaseiPatternExpression, AccentiPatternExpression, CharacterLiteral
PatternExpressionItems = Union[
CaseiPatternExpression, AccentiPatternExpression, StrictStr
]
CharacterClauseItems = Union[
CaseiCharacterExpression,
AccentiCharacterExpression,
StrictStr,
]
CharacterExpression = Union[
CharacterClause,
PropertyRef,
FunctionRef,
]

# Extra types to match the cql2-text grammar better
Expand Down Expand Up @@ -403,6 +421,7 @@ def __str__(self) -> str:
BooleanExpression.model_rebuild()
CaseiCharacterExpression.model_rebuild()
CaseiPatternExpression.model_rebuild()
CharacterClause.model_rebuild()
DateInstant.model_rebuild()
Function.model_rebuild()
FunctionRef.model_rebuild()
Expand All @@ -412,6 +431,7 @@ def __str__(self) -> str:
IsLikePredicate.model_rebuild()
IsNullPredicate.model_rebuild()
NotExpression.model_rebuild()
PatternExpression.model_rebuild()
PropertyRef.model_rebuild()
SpatialPredicate.model_rebuild()
TemporalPredicate.model_rebuild()
Expand Down

0 comments on commit 204c0b9

Please sign in to comment.