Add NodeTraverser-based expression parser (default) with legacy escape hatch#6
Merged
Merged
Conversation
e5d3d50 to
39b5719
Compare
Contributor
Test Results1 317 tests +2 1 269 ✅ - 10 34s ⏱️ -1s Results for commit 954ebe6. ± Comparison against base commit 9b60777. This pull request skips 12 tests.♻️ This comment has been updated with latest results. |
…e hatch Adds a `NodeTraverserParser` built on polars' `_plr` API (`LazyFrame._ldf.visit()` + `add_expressions` + `view_expression`). It produces the same `BaseExprNode` tree the JSON-serialization based `ExprParser` does, so it plugs in behind `get_parsed_expr` without changing the downstream visitor surface. The new parser is the default. Set `POLARS_IO_TOOLS_USE_LEGACY_EXPR_PARSER=1` to fall back to the legacy parser for one release as an escape hatch. The new parser walks the post-optimization typed expression view, which is exactly the shape that reaches a custom IO source predicate via `register_io_source`. Several expression shapes the legacy parser handles (top-level/nested aliases, any_horizontal / all_horizontal, selectors / wildcards, list / struct / explode) are rewritten away by the polars optimizer before any predicate callback runs, so they are dead code on the predicate-pushdown path. The tests covering those shapes are marked `skip_unoptimized_expression_shape` and run only under the legacy escape hatch. Imports the parser node module via `polars._plr._expr_nodes` with a fallback to the older `polars.polars._expr_nodes` path (renamed in polars 1.32), and pins `polars>=1.8` to match the validated floor. Signed-off-by: Pascal Tomecek <40371786+ptomecek@users.noreply.github.com>
39b5719 to
954ebe6
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.
Summary
Adds a
NodeTraverserParserbuilt on polars'_plrAPI (LazyFrame._ldf.visit()+add_expressions+view_expression). It produces the sameBaseExprNodetree the JSON-serialization basedExprParserdoes, so it plugs in behindget_parsed_exprwithout changing the downstream visitor surface.The new parser is the default.
POLARS_IO_TOOLS_USE_LEGACY_EXPR_PARSER=1falls back to the legacy parser for one release as an escape hatch.Motivation
NodeTraverserwalks the post-optimization typed expression view, which is exactly the shape that arrives at a custom IO source plugin viapolars.io.plugins.register_io_source. It is structurally cleaner than the JSON-based parser: typed_expr_nodesdispatch (Operator, function-category enums,Literal.value/Cast.dtype) withexpr.meta.pop()only for per-child sub-expression attribution.Several expression shapes the legacy parser handles (top-level/nested aliases,
any_horizontal/all_horizontal, selectors / wildcards, list / struct / explode) are rewritten away by the polars optimizer before any IO-source predicate callback runs, so they are dead code on the predicate-pushdown path. The tests covering those shapes are markedskip_unoptimized_expression_shapeand run only under the legacy escape hatch.Known limitation
polars'
NodeTraverserdoes not yet expose typed views for list (col.list.*) and array (col.arr.*) functions —view_expressionraisesNotImplementedErrorfor them. Under the new default parser those subtrees degrade toUnknownNode, so a predicate containing them is not pushed down (the filter is still applied correctly by polars; only pushdown efficiency is lost).POLARS_IO_TOOLS_USE_LEGACY_EXPR_PARSER=1recovers full parsing for these shapes. This is documented inline inNodeTraverserParser._parse.Compatibility
polars._plr._expr_nodeswith a fallback to the olderpolars.polars._expr_nodespath (renamed in polars 1.32).polars>=1.8to match the validated floor.Test results
POLARS_IO_TOOLS_USE_LEGACY_EXPR_PARSER=1: the skipped tests run and pass under the legacy parser.