feat(cql2-text): parse the A_* array predicates - #177
Open
C1-BA-B1-F3 wants to merge 4 commits into
Open
C1-BA-B1-F3 wants to merge 4 commits into
C1-BA-B1-F3 wants to merge 4 commits into
Conversation
The unquoted attribute regex /[a-zA-Z][a-zA-Z_:0-9.]+/ required at least two characters, so expressions like 'a = 1' or 'S_INTERSECTS(g, BBOX(...))' failed to parse. Change the trailing .+ to .* so a single-letter identifier is accepted. Fixes geopython#165
A GeoJSON bbox literal is [minx, miny, maxx, maxy], but parsers/cql2_json/parser.py unpacked it directly into values.Envelope(*bbox) whose field order is (x1, x2, y1, y2) == (minx, maxx, miny, maxy). The two conventions were conflated, so longitudes and latitudes were silently swapped. Reindex explicitly: Envelope(b[0], b[2], b[1], b[3]). Fixes geopython#163
OGC 21-065r2 defines BETWEEN with a flat 3-element args array [operand, low, high]. The parser only accepted the draft nested shape [operand, [low, high]], so a spec-conformant client raised TypeError. Accept both: nested when args[1] is a list, flat when it is not. Fixes geopython#162
Author
|
Heads-up for the maintainer: #161 (open since 2026-08-02, "Add CQL2 array predicates, cql-json Differences, so you can pick whichever you prefer:
Happy to close this one if you would rather take #161 — just say so. |
…NEDBY, A_OVERLAPS)
The cql2_text grammar had no rules for array predicates, so expressions
like A_CONTAINS(values, ('a', 'b', 'c')) raised UnexpectedToken on the
comma. The cql2_json parser already handles them.
Add an array_predicate rule with a parenthesised expression list on the
right-hand side, wire it into the predicate alternatives, and map the
operators through ARRAY_PREDICATES_MAP in the transformer.
Fixes geopython#160
C1-BA-B1-F3
force-pushed
the
fix/cql2-text-array-predicates
branch
from
October 3, 2026 07:27
bd23b71 to
3138da8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #160.
A_CONTAINS(arrayattr, ('a', 'b', 'c'))raisedUnexpected token Token('COMMA', ','): the cql2-text grammar had no arrayliteral and no
A_*predicate, so the call fell through to the genericfuncrule (attribute "(" expression ("," expression)* ")") and died on thecomma — a parenthesized list is not an
expression.cql2-json already parses the same filter, and
cql2.ARRAY_PREDICATES_MAPalready carries the mapping, so the gap was only in the text parser:
arrayrule — a parenthesized list — reachable only from the arraypredicate, so its parentheses cannot be confused with a parenthesized
expression elsewhere;
A_EQUALS/A_CONTAINS/A_CONTAINEDBY/A_OVERLAPSkeywords, case-insensitive like the
S_*ones;ARRAY_PREDICATES_MAP, so bothparsers produce the same AST.
Tests
8 cases added to
tests/parsers/cql2_text/test_parser.py: the issue's exactreproduction, all four operators, a single-element array, lowercase input, and
an array predicate inside an
ANDcondition.testextra (excluding the modules that need a liveElasticsearch/OpenSearch/Solr or GDAL): 324 passed / 62 skipped / 37
errors, against a 316 / 62 / 37 baseline on
main— the delta isexactly the 8 new tests; the 37 errors are the network-backed backend
suites and are unrelated.
ruff/ruff formatclean;mypyreports the same pre-existingvalues.pyerrors asmain.The grammar's only reported conflict is the pre-existing
Shift/Reduce conflict for terminal RPAR ... <literal : bbox>; the new rulesadd none, because the
A_*andS_*keyword terminals disambiguate the twospatial_predicatealternatives before any(is read.