From 3e80c455639856b845c8dedd2be45df4b91d7620 Mon Sep 17 00:00:00 2001 From: Nikhil Garg Date: Tue, 24 Dec 2024 16:49:32 -0800 Subject: [PATCH] expressions: add zip, repeat, sqrt, log, pow along with docs --- .wordlist.txt | 3 + docs/api.yml | 5 + .../api-reference/expressions/basic.py | 54 ++- .../examples/api-reference/expressions/num.py | 77 +++++ .../api-reference/expressions/num/log.md | 34 ++ .../api-reference/expressions/num/pow.md | 45 +++ .../api-reference/expressions/num/sqrt.md | 31 ++ .../pages/api-reference/expressions/repeat.md | 39 +++ docs/pages/api-reference/expressions/zip.md | 48 +++ fennel/CHANGELOG.md | 3 + .../test_complex_autogen_extractor.py | 5 +- fennel/client_tests/test_expr.py | 6 +- fennel/dtypes/dtypes.py | 28 +- fennel/expr/__init__.py | 13 +- fennel/expr/expr.py | 66 +++- fennel/expr/serializer.py | 41 +++ fennel/expr/test_expr.py | 325 ++++++++++++++++-- fennel/expr/test_invalid_expr.py | 5 +- fennel/expr/visitor.py | 84 ++++- fennel/gen/expression_pb2.py | 266 +++++++------- fennel/gen/expression_pb2.pyi | 144 +++++++- fennel/internal_lib/schema/schema.py | 2 + poetry.lock | 78 ++--- pyproject.toml | 6 +- 24 files changed, 1193 insertions(+), 215 deletions(-) create mode 100644 docs/pages/api-reference/expressions/num/log.md create mode 100644 docs/pages/api-reference/expressions/num/pow.md create mode 100644 docs/pages/api-reference/expressions/num/sqrt.md create mode 100644 docs/pages/api-reference/expressions/repeat.md create mode 100644 docs/pages/api-reference/expressions/zip.md diff --git a/.wordlist.txt b/.wordlist.txt index e87e60ee5..be6d87c94 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -35,6 +35,7 @@ DescribeStreamSummary disambiguity Dockerfile expr +exponentiate Eval eval endswith @@ -127,6 +128,8 @@ Secret ShardIteratorType Signifier SnapshotData +sqrt +Sqrt Stddev Subprocessor SubscribeToShard diff --git a/docs/api.yml b/docs/api.yml index 6a9c6a509..24b809c40 100644 --- a/docs/api.yml +++ b/docs/api.yml @@ -108,8 +108,10 @@ sidebar: - "api-reference/expressions/lit" - "api-reference/expressions/not" - "api-reference/expressions/now" + - "api-reference/expressions/repeat" - "api-reference/expressions/typeof" - "api-reference/expressions/when" + - "api-reference/expressions/zip" - slug: "api-reference/expressions/dt" title: "Datetime Expressions" @@ -146,7 +148,10 @@ sidebar: - "api-reference/expressions/num/abs" - "api-reference/expressions/num/ceil" - "api-reference/expressions/num/floor" + - "api-reference/expressions/num/log" + - "api-reference/expressions/num/pow" - "api-reference/expressions/num/round" + - "api-reference/expressions/num/sqrt" - "api-reference/expressions/num/to_string" - slug: "api-reference/expressions/str" diff --git a/docs/examples/api-reference/expressions/basic.py b/docs/examples/api-reference/expressions/basic.py index 3a27c2e82..249c6bc68 100644 --- a/docs/examples/api-reference/expressions/basic.py +++ b/docs/examples/api-reference/expressions/basic.py @@ -1,7 +1,7 @@ from datetime import datetime import pytest -from typing import Optional +from typing import Optional, List import pandas as pd @@ -176,8 +176,58 @@ def test_now(): {"birthdate": [datetime(1997, 12, 24), datetime(2001, 1, 21), None]} ) assert expr.eval(df, schema={"birthdate": Optional[datetime]}).tolist() == [ - 26, + 27, 23, pd.NA, ] # /docsnip + + +def test_repeat(): + # docsnip repeat + from fennel.expr import repeat, col + + # docsnip-highlight next-line + expr = repeat(col("x"), col("y")) + + assert expr.typeof(schema={"x": bool, "y": int}) == List[bool] + + # can be evaluated with a dataframe + df = pd.DataFrame({"x": [True, False, True], "y": [1, 2, 3]}) + assert expr.eval(df, schema={"x": bool, "y": int}).tolist() == [ + [True], + [False, False], + [True, True, True], + ] + # /docsnip + + +def test_zip(): + # docsnip zip + from fennel.lib.schema import struct + from fennel.expr import col + + @struct + class MyStruct: + a: int + b: float + + # docsnip-highlight next-line + expr = MyStruct.zip(a=col("x"), b=col("y")) + + expected = List[MyStruct] + schema = {"x": List[int], "y": List[float]} + assert expr.matches_type(expected, schema) + + # note that output is truncated to the length of the shortest list + df = pd.DataFrame( + {"x": [[1, 2], [3, 4], []], "y": [[1.0, 2.0], [3.0], [4.0]]} + ) + assert expr.eval( + df, schema={"x": List[int], "y": List[float]} + ).tolist() == [ + [MyStruct(a=1, b=1.0), MyStruct(a=2, b=2.0)], + [MyStruct(a=3, b=3.0)], + [], + ] + # /docsnip diff --git a/docs/examples/api-reference/expressions/num.py b/docs/examples/api-reference/expressions/num.py index 08125dc3e..1d3b78648 100644 --- a/docs/examples/api-reference/expressions/num.py +++ b/docs/examples/api-reference/expressions/num.py @@ -1,4 +1,5 @@ import pytest +import numpy as np from typing import Optional import pandas as pd @@ -146,3 +147,79 @@ def test_to_string(): pd.NA, ] # /docsnip + + +def test_sqrt(): + # docsnip sqrt + from fennel.expr import col + + # docsnip-highlight next-line + expr = col("x").num.sqrt() + + assert expr.typeof(schema={"x": int}) == float + assert expr.typeof(schema={"x": Optional[int]}) == Optional[float] + assert expr.typeof(schema={"x": float}) == float + assert expr.typeof(schema={"x": Optional[float]}) == Optional[float] + + df = pd.DataFrame({"x": pd.Series([1.1, -2.3, 4.0])}) + assert expr.eval(df, schema={"x": Optional[float]}).tolist() == [ + 1.0488088481701516, + pd.NA, # this is nan in pandas, sqrt of negative number + 2.0, + ] + # /docsnip + + +def test_log(): + # docsnip log + from fennel.expr import col + + # docsnip-highlight next-line + expr = col("x").num.log(base=2.0) + + assert expr.typeof(schema={"x": int}) == float + assert expr.typeof(schema={"x": Optional[int]}) == Optional[float] + assert expr.typeof(schema={"x": float}) == float + assert expr.typeof(schema={"x": Optional[float]}) == Optional[float] + + df = pd.DataFrame({"x": pd.Series([1.1, -2.3, 4.0])}) + assert expr.eval(df, schema={"x": Optional[float]}).tolist() == [ + 0.13750352374993502, + pd.NA, # nan in pandas, log of negative number + 2.0, + ] + # /docsnip + + +def test_pow(): + # docsnip pow + from fennel.expr import col, lit + + # docsnip-highlight next-line + expr = col("x").num.pow(lit(2)) + + assert expr.typeof(schema={"x": int}) == int + assert expr.typeof(schema={"x": Optional[int]}) == Optional[int] + assert expr.typeof(schema={"x": float}) == float + assert expr.typeof(schema={"x": Optional[float]}) == Optional[float] + + df = pd.DataFrame({"x": pd.Series([1, 2, 4])}) + assert expr.eval(df, schema={"x": int}).tolist() == [ + 1, + 4, + 16, + ] + + # negative integer exponent raises error if base is also an integer + with pytest.raises(Exception): + expr = lit(2).num.pow(lit(-2)) + expr.eval(df, schema={"x": int}) + + # but works if either base or exponent is a float + expr = lit(2).num.pow(lit(-2.0)) + assert expr.eval(df, schema={"x": int}).tolist() == [ + 0.25, + 0.25, + 0.25, + ] + # /docsnip diff --git a/docs/pages/api-reference/expressions/num/log.md b/docs/pages/api-reference/expressions/num/log.md new file mode 100644 index 000000000..26f1aad6f --- /dev/null +++ b/docs/pages/api-reference/expressions/num/log.md @@ -0,0 +1,34 @@ +--- +title: Log +order: 0 +status: published +--- + +### Log + +Function in `num` namespace to get the logarithm of a number. + +#### Parameters + +The base of the logarithm. By default, the base is set to `e` (Euler's number). + + +#### Returns + +Returns an expression object denoting the logarithm of the input data. The +data type of the resulting expression is `float` if the input was `int` or +`float` and `Optional[float]` if the input was `Optional[int]` or +`Optional[float]`. + +For negative numbers, the result is `NaN` (Not a Number). + + +
+
+ +#### Errors + +Error during `typeof` or `eval` if the input expression is not of type int, +float, optional int or optional float. + \ No newline at end of file diff --git a/docs/pages/api-reference/expressions/num/pow.md b/docs/pages/api-reference/expressions/num/pow.md new file mode 100644 index 000000000..a6a0c5e2c --- /dev/null +++ b/docs/pages/api-reference/expressions/num/pow.md @@ -0,0 +1,45 @@ +--- +title: Pow +order: 0 +status: published +--- + +### Pow + +Function in `num` namespace to exponentiate a number. + +#### Parameters + +The exponent to which the base is raised - expected to be a numeric expression. + + +#### Returns + +Returns an expression object denoting the result of the exponentiation. + +The base data type of the resulting expression is `int` if both the base and +exponent are `int`, otherwise it is `float`. + +If any of the base or exponent is `Optional`, the resulting expression is +also `Optional` of the base data type. + + +
+
+ +#### Errors + + +Error during `typeof` or `eval` if the input expression is not of type int, +float, optional int or optional float. + + + + +A runtime error will be raised if the exponent is a negative integer and the +base is also an integer. + +In such cases, it's advised to convert either the base or the exponent to be a +float. + diff --git a/docs/pages/api-reference/expressions/num/sqrt.md b/docs/pages/api-reference/expressions/num/sqrt.md new file mode 100644 index 000000000..710cd16b6 --- /dev/null +++ b/docs/pages/api-reference/expressions/num/sqrt.md @@ -0,0 +1,31 @@ +--- +title: Sqrt +order: 0 +status: published +--- + +### Sqrt + +Function in `num` namespace to get the square root of a number. + +#### Returns + +Returns an expression object denoting the square root of the input data. + +The data type of the resulting expression is `float` if the input is `int` or +`float` and `Optional[float]` if the input is `Optional[int]` or `Optional[float]`. + + +:::info +The square root of a negative number is represented as `NaN` in the output. +::: + +
+
+ +#### Errors + +Error during `typeof` or `eval` if the input expression is not of type int, +float, optional int or optional float. + diff --git a/docs/pages/api-reference/expressions/repeat.md b/docs/pages/api-reference/expressions/repeat.md new file mode 100644 index 000000000..721ee5a58 --- /dev/null +++ b/docs/pages/api-reference/expressions/repeat.md @@ -0,0 +1,39 @@ +--- +title: Repeat +order: 0 +status: published +--- +### Repeat + +Repeat an expression `n` times to create a list. + +#### Parameters + +The expression to repeat. + + + +The number of times to repeat the value - can evaluate to a different count for +each row. + + + +
+
+ +#### Returns + +Returns an expression object denoting the result of the repeat expression. + + + +#### Errors + +An error is thrown if the `by` expression is not of type int. +In addition, certain types (e.g. lists) are not supported as input for `value`. + + + +An error is thrown if the `by` expression evaluates to a negative integer. + diff --git a/docs/pages/api-reference/expressions/zip.md b/docs/pages/api-reference/expressions/zip.md new file mode 100644 index 000000000..8e741d3eb --- /dev/null +++ b/docs/pages/api-reference/expressions/zip.md @@ -0,0 +1,48 @@ +--- +title: Zip +order: 0 +status: published +--- +### Zip + +Zip two or more lists into a list of structs. + +#### Parameters + +The struct to hold the zipped values. Unlike other top level expressions, +`zip` is written as `Struct.zip(kwarg1=expr1, kwarg2=expr2, ...)`. + + + +A dictionary of key-value pairs where the key is the name of the field in the +struct and the value is the expression to zip. + +Expressions are expected to evaluate to lists of a type that can be converted to +the corresponding field type in the struct. + + + +
+
+ +#### Returns + +Returns an expression object denoting the result of the zip expression. + + +:::info +When zipping lists of unequal length, similar to Python's zip function, the +resulting list will be truncated to the length of the shortest list, possibly +zero. +::: + +#### Errors + +An error is thrown if the types of the lists to zip are not compatible with the +field types in the struct. + + + +An error is thrown if the expressions to zip don't evaluate to lists. + diff --git a/fennel/CHANGELOG.md b/fennel/CHANGELOG.md index 66cb5034d..842a87103 100644 --- a/fennel/CHANGELOG.md +++ b/fennel/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## [1.5.63] - 2024-12-24 +- Add support for zip, repeat, pow, log, and sqrt expressions + ## [1.5.62] - 2024-12-16 - Fix casting for empty dataframes. diff --git a/fennel/client_tests/test_complex_autogen_extractor.py b/fennel/client_tests/test_complex_autogen_extractor.py index b869b2388..36f63599f 100644 --- a/fennel/client_tests/test_complex_autogen_extractor.py +++ b/fennel/client_tests/test_complex_autogen_extractor.py @@ -346,7 +346,10 @@ def test_complex_auto_gen_extractors(client): assert extracted_df["RiderFeatures.dl_state"].to_list() == ["US", "Unknown"] assert extracted_df["RiderFeatures.is_us_dl"].to_list() == [True, False] - age_years = datetime.now(timezone.utc).year - 2000 + age_years = ( + datetime.now() - datetime(2000, 1, 1, 0, 0, 0) + ).total_seconds() / (60 * 60 * 24 * 365) + age_years = int(age_years + 0.001) assert extracted_df["RiderFeatures.age_years"].to_list() == [30, age_years] assert extracted_df["RiderFeatures.dl_state_population"].to_list() == [ 328200000, diff --git a/fennel/client_tests/test_expr.py b/fennel/client_tests/test_expr.py index fd01f545a..32f84f032 100644 --- a/fennel/client_tests/test_expr.py +++ b/fennel/client_tests/test_expr.py @@ -89,7 +89,7 @@ class UserInfoFeatures: "Rachel", pd.NA, ] - assert df["UserInfoFeatures.age"].tolist() == [54, 44, 34, 26, 23, pd.NA] + assert df["UserInfoFeatures.age"].tolist() == [55, 44, 34, 27, 23, pd.NA] assert df["UserInfoFeatures.country"].tolist() == [ "India", "USA", @@ -132,10 +132,10 @@ class UserInfoFeatures: pd.NA, ] assert df["UserInfoFeatures.age"].tolist() == [ - 53, + 54, 43, 33, - 25, + 26, 22, pd.NA, ] diff --git a/fennel/dtypes/dtypes.py b/fennel/dtypes/dtypes.py index e01f4f879..0756a9de6 100644 --- a/fennel/dtypes/dtypes.py +++ b/fennel/dtypes/dtypes.py @@ -86,6 +86,28 @@ def make_struct_expr(cls, **kwargs): return make_struct(fields, cls) +def eq(cls): + names = [field.name for field in dataclasses.fields(cls)] + + def eq_impl(self, other): + print("inside dataclass eq") + # verify that the other is a struct of the same type + for name in names: + if not hasattr(other, name): + return False + if getattr(self, name) != getattr(other, name): + return False + return True + + return eq_impl + + +def zip_expr(cls, **kwargs): + from fennel.expr.expr import zip + + return zip(cls, kwargs) + + def struct(cls): for name, member in inspect.getmembers(cls): if inspect.isfunction(member) and name in cls.__dict__: @@ -143,7 +165,11 @@ def struct(cls): setattr(cls, FENNEL_STRUCT_DEPENDENCIES_SRC_CODE, dependency_code) cls.as_json = as_json cls.expr = partial(make_struct_expr, cls) - return dataclasses.dataclass(cls) + cls.zip = partial(zip_expr, cls) + decorator = dataclasses.dataclass(eq=False) + cls = decorator(cls) + cls.__eq__ = eq(cls) + return cls # --------------------------------------------------------------------- diff --git a/fennel/expr/__init__.py b/fennel/expr/__init__.py index 43e0dc3e8..24f518aa3 100644 --- a/fennel/expr/__init__.py +++ b/fennel/expr/__init__.py @@ -1,12 +1,13 @@ from fennel.expr.expr import ( col, - lit, - when, - make_struct, - var, datetime, - from_epoch, - now, Expr, + from_epoch, InvalidExprException, + lit, + make_struct, + now, + repeat, + var, + when, ) diff --git a/fennel/expr/expr.py b/fennel/expr/expr.py index b41ece1cb..327856404 100644 --- a/fennel/expr/expr.py +++ b/fennel/expr/expr.py @@ -3,6 +3,7 @@ from enum import Enum import copy import json +import math from dataclasses import dataclass from typing import Any, Callable, Dict, Type, Optional import pandas as pd @@ -486,6 +487,20 @@ class NumToStr(MathOp): pass +class Sqrt(MathOp): + pass + + +@dataclass +class Pow(MathOp): + exponent: Expr + + +@dataclass +class Log(MathOp): + base: float + + class MathNoop(MathOp): pass @@ -511,6 +526,15 @@ def floor(self) -> _Number: def to_string(self) -> _String: return _String(_Number(self, NumToStr()), StringNoop()) + def sqrt(self) -> _Number: + return _Number(self, Sqrt()) + + def pow(self, exponent: Expr) -> _Number: + return _Number(self, Pow(exponent)) + + def log(self, base: float = math.e) -> _Number: + return _Number(self, Log(base)) + ######################################################### # String Functions @@ -1063,6 +1087,37 @@ def __str__(self) -> str: return f"{self.left} {self.op} {self.right}" +class Repeat(Expr): + def __init__(self, value: Expr, by: Expr): + self.value = make_expr(value) + self.by = make_expr(by) + if not isinstance(self.value, Expr): + raise InvalidExprException( + "`value` in repeat can only be an expression but got %s instead" + % self.value + ) + if not isinstance(self.by, Expr): + raise InvalidExprException( + "`by` in repeat expected to be an expression but got %s instead" + % self.by + ) + super(Repeat, self).__init__() + + def __str__(self) -> str: + return f"repeat({self.value}, {self.by})" + + +class Zip(Expr): + def __init__(self, struct_type: Type, fields: Dict[str, Expr]): + self.struct_type = struct_type + self.fields = {k: make_expr(v) for k, v in fields.items()} + super(Zip, self).__init__() + + def __str__(self) -> str: + kwargs = [f"{k}={v}" for k, v in self.fields.items()] + return f"{self.struct_type}.zip({', '.join(kwargs)})" + + class When(Expr): def __init__(self, expr: Expr, root: Optional[Expr] = None): self.expr = make_expr(expr) @@ -1085,7 +1140,7 @@ def when(self, expr: Expr) -> When: self._chained_when = When(expr, self.root) # type: ignore return self._chained_when # type: ignore - def otherwise(self, expr: Expr) -> Otherwise: + def otherwise(self, expr: Expr) -> When: self._otherwise = Otherwise(make_expr(expr), self.root) # type: ignore return self._otherwise # type: ignore @@ -1202,6 +1257,15 @@ def make_struct(fields: Dict[str, Expr], type: Type) -> Expr: return MakeStruct(fields, type) +def zip(struct_type: Type, fields: Dict[str, Expr]) -> Expr: + fields = {k: make_expr(v) for k, v in fields.items()} + return Zip(struct_type, fields) + + +def repeat(value: Expr, by: Expr) -> Expr: + return Repeat(value, by) + + def from_epoch(duration: Expr, unit: str | TimeUnit) -> _DateTime: duration = make_expr(duration) unit = TimeUnit.from_string(unit) diff --git a/fennel/expr/serializer.py b/fennel/expr/serializer.py index 784a2445b..22cf9f958 100644 --- a/fennel/expr/serializer.py +++ b/fennel/expr/serializer.py @@ -47,6 +47,9 @@ MathNoop, Round, Ceil, + Sqrt, + Pow, + Log, NumToStr, Abs, Floor, @@ -67,6 +70,8 @@ DictLen, DictNoop, DateTimeNoop, + Zip, + Repeat, ) @@ -234,6 +239,18 @@ def visitNumber(self, obj): expr.math_fn.fn.CopyFrom(proto.MathOp(floor=proto.Floor())) elif isinstance(obj.op, NumToStr): expr.math_fn.fn.CopyFrom(proto.MathOp(to_string=proto.ToString())) + elif isinstance(obj.op, Sqrt): + expr.math_fn.fn.CopyFrom(proto.MathOp(sqrt=proto.Sqrt())) + elif isinstance(obj.op, Pow): + expr.math_fn.fn.CopyFrom( + proto.MathOp( + pow=proto.Pow(exponent=self.visit(obj.op.exponent)) + ) + ) + elif isinstance(obj.op, Log): + expr.math_fn.fn.CopyFrom( + proto.MathOp(log=proto.Log(base=obj.op.base)) + ) else: raise InvalidExprException("invalid number operation: %s" % obj.op) expr.math_fn.operand.CopyFrom(self.visit(obj.operand)) @@ -503,6 +520,30 @@ def visitNow(self, obj): expr.now.CopyFrom(proto.Now()) return expr + def visitZip(self, obj): + expr = proto.Expr() + for field, value in obj.fields.items(): + field_expr = expr.zip.fields.get_or_create(field) + field_expr.CopyFrom(self.visit(value)) + + # Ensure get_datatype returns a correct protobuf message of type StructType + dtype = get_datatype(obj.struct_type) + if dtype.struct_type is None: + raise InvalidExprException( + "invalid zip: expected struct_type to be a StructType, found {}".format( + dtype + ) + ) + expr.zip.struct_type.CopyFrom(dtype.struct_type) + return expr + + def visitRepeat(self, obj): + expr = proto.Expr() + expr.repeat.CopyFrom( + proto.Repeat(expr=self.visit(obj.value), count=self.visit(obj.by)) + ) + return expr + def val_as_json(val: Any) -> str: if isinstance(val, str): diff --git a/fennel/expr/test_expr.py b/fennel/expr/test_expr.py index 4b9a02b16..e7caeb598 100644 --- a/fennel/expr/test_expr.py +++ b/fennel/expr/test_expr.py @@ -8,11 +8,12 @@ from fennel.datasets import dataset from fennel.dtypes.dtypes import struct -from fennel.expr import col, when, lit, now +from fennel.expr import col, when, lit, now, var from fennel.expr.expr import ( TimeUnit, from_epoch, make_struct, + repeat, ) from fennel.expr.visitor import ExprPrinter, FetchReferences from fennel.expr.serializer import ExprSerializer @@ -437,10 +438,13 @@ def compare_values(received, expected, dtype): ), f"Expected {e}, got {r} for field {field.name} in struct {act}" else: compare_values([r], [e], field.type) + elif hasattr(dtype, "__origin__") and dtype.__origin__ is list: + for act, exp in zip(received, expected): + compare_values(act, exp, dtype.__args__[0]) else: assert ( list(received) == expected - ), f"Expected {expected}, got {received} for dtype {dtype}" + ), f"Expected {expected} of type {dtype}, got {received} of type {type(received)}" def check_test_case(test_case: ExprTestCase): @@ -475,7 +479,10 @@ def check_test_case(test_case: ExprTestCase): ) else: assert ( - test_case.expr.typeof(test_case.schema) == test_case.expected_dtype + test_case.expr.matches_type( + test_case.expected_dtype, test_case.schema + ) + # test_case.expr.typeof(test_case.schema) == test_case.expected_dtype ) # Test eval @@ -538,6 +545,25 @@ class A: z: str +@struct +class Point: + x: int + y: int + + +@struct +class PointF: + x: Optional[float] + y: Optional[float] + + +@struct +class Point3D: + x: int + y: int + z: int + + @struct class Nested: a: A @@ -1138,16 +1164,277 @@ def test_parse_str_to_and_from_datetime(): assert ret.tolist() == df["a"].tolist() -def test_make_struct(): +def test_repeat(): + cases = [ + ExprTestCase( + expr=repeat(lit(1), 3), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display="REPEAT(1, 3)", + refs=set(), + eval_result=[[1, 1, 1], [1, 1, 1], [1, 1, 1]], + expected_dtype=List[int], + proto_json=None, + ), + ExprTestCase( + expr=repeat(col("a"), 3), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display='REPEAT(col("a"), 3)', + refs={"a"}, + eval_result=[[1, 1, 1], [2, 2, 2], [3, 3, 3]], + expected_dtype=List[int], + proto_json=None, + ), + ExprTestCase( + expr=repeat(col("a"), lit(3)), + df=pd.DataFrame({"a": [True, False, True]}), + schema={"a": bool}, + display='REPEAT(col("a"), 3)', + refs={"a"}, + eval_result=[ + [True, True, True], + [False, False, False], + [True, True, True], + ], + expected_dtype=List[bool], + proto_json=None, + ), + ExprTestCase( + expr=repeat(col("a"), lit(3)), + df=pd.DataFrame({"a": [1.0, None, 3.0]}), + schema={"a": Optional[float]}, + display='REPEAT(col("a"), 3)', + refs={"a"}, + eval_result=[ + [1.0, 1.0, 1.0], + [pd.NA, pd.NA, pd.NA], + [3.0, 3.0, 3.0], + ], + expected_dtype=List[Optional[float]], + proto_json=None, + ), + ExprTestCase( + expr=repeat(col("a"), lit(0)), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display='REPEAT(col("a"), 0)', + refs={"a"}, + eval_result=[[], [], []], + expected_dtype=List[int], + proto_json=None, + ), + ] + for case in cases: + check_test_case(case) + + # repeat with negative count + expr = repeat(col("a"), lit(-1)) + with pytest.raises(BaseException): + expr.eval(pd.DataFrame({"a": [1, 2, 3]}), {"a": int}) + + +def test_sqrt(): + cases = [ + ExprTestCase( + expr=lit(4).num.sqrt(), + df=pd.DataFrame({"a": [1, 4, 9]}), + schema={"a": int}, + display="SQRT(4)", + refs=set(), + eval_result=[2.0, 2.0, 2.0], + expected_dtype=float, + proto_json=None, + ), + ExprTestCase( + expr=col("a").num.sqrt(), + df=pd.DataFrame({"a": [1, 4, 9]}), + schema={"a": int}, + display='SQRT(col("a"))', + refs={"a"}, + eval_result=[1.0, 2.0, 3.0], + expected_dtype=float, + proto_json=None, + ), + ] + + for case in cases: + check_test_case(case) + + +def test_pow(): + cases = [ + ExprTestCase( + expr=lit(2).num.pow(lit(3)), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display="POW(2, 3)", + refs=set(), + eval_result=[8, 8, 8], + expected_dtype=int, + proto_json=None, + ), + ExprTestCase( + expr=col("a").num.pow(lit(3)), + df=pd.DataFrame({"a": [1.0, 2.0, 3.0]}), + schema={"a": float}, + display='POW(col("a"), 3)', + refs={"a"}, + eval_result=[1.0, 8.0, 27.0], + expected_dtype=float, + proto_json=None, + ), + ExprTestCase( + expr=col("a").num.pow(lit(-2.0)), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display='POW(col("a"), -2.0)', + refs={"a"}, + eval_result=[1.0, 0.25, 0.1111111111111111], + expected_dtype=float, + proto_json=None, + ), + ] + for case in cases: + check_test_case(case) + + expr = col("a").num.pow(lit(-2)) + with pytest.raises(Exception): + expr.eval(pd.DataFrame({"a": [1, 2, 3]}), {"a": int}) + + +def test_log(): + cases = [ + ExprTestCase( + expr=lit(100).num.log(10.0), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display="LOG(100, base=10.0)", + refs=set(), + eval_result=[2.0, 2.0, 2.0], + expected_dtype=float, + proto_json=None, + ), + ExprTestCase( + expr=col("a").num.log(), + df=pd.DataFrame({"a": [1, 2, 3]}), + schema={"a": int}, + display='LOG(col("a"), base=2.718281828459045)', + refs={"a"}, + eval_result=[0.0, 0.6931471805599453, 1.0986122886681098], + expected_dtype=float, + proto_json=None, + ), + ] + for case in cases: + check_test_case(case) + + +def test_zip(): cases = [ # Make a struct ExprTestCase( - expr=( - make_struct( - {"x": col("a"), "y": col("a") + col("b"), "z": "constant"}, - A, - ) + expr=A.zip( + x=col("a"), + y=col("b"), + z=col("b").list.map("e", var("e").num.to_string()), + ), + df=pd.DataFrame({"a": [[1, 2], [3], []], "b": [[4, 5], [6], []]}), + schema={"a": List[int], "b": List[int]}, + display="""ZIP(A, x=col("a"), y=col("b"), z=LIST_MAP(col("b"), "e", TO_STRING(var("e"))))""", + refs={"a", "b"}, + eval_result=[ + [A(1, 4, "4"), A(2, 5, "5")], + [A(3, 6, "6")], + [], + ], + expected_dtype=List[A], + proto_json=None, + ), + ExprTestCase( + expr=Point.zip(x=col("a"), y=col("b")).list.map( + "s", + var("s").struct.get("x") / (lit(1) + var("s").struct.get("y")), + ), + df=pd.DataFrame({"a": [[1, 2], [3], []], "b": [[4, 5], [6], []]}), + schema={"a": List[int], "b": List[int]}, + display="""LIST_MAP(ZIP(Point, x=col("a"), y=col("b")), "s", (var("s").x / (1 + var("s").y)))""", + refs={"a", "b"}, + eval_result=[ + [0.2, 0.3333333333333333], + [3.0 / 7.0], + [], + ], + expected_dtype=List[float], + proto_json=None, + ), + ExprTestCase( + expr=PointF.zip( + x=col("a"), + y=col("b").list.map( + "n", + when(var("n") > lit(5)) + .then(var("n") * lit(2)) + .otherwise(lit(None)), + ), + ), + df=pd.DataFrame({"a": [[1, 2], [3], []], "b": [[4, 5], [6], []]}), + schema={"a": List[int], "b": List[int]}, + display="""ZIP(PointF, x=col("a"), y=LIST_MAP(col("b"), "n", WHEN (var("n") > 5) THEN (var("n") * 2) ELSE null))""", + refs={"a", "b"}, + eval_result=[ + [PointF(1.0, None), PointF(2.0, None)], + [PointF(3.0, 12.0)], + [], + ], + expected_dtype=List[PointF], + proto_json=None, + ), + # zip works with the shortest list + ExprTestCase( + expr=Point.zip(x=col("a"), y=col("b")), + df=pd.DataFrame( + {"a": [[1, 2], [3], []], "b": [[4, 5, 6], [6], [7]]} + ), + schema={"a": List[int], "b": List[int]}, + display="""ZIP(Point, x=col("a"), y=col("b"))""", + refs={"a", "b"}, + eval_result=[ + [Point(1, 4), Point(2, 5)], + [Point(3, 6)], + [], + ], + expected_dtype=List[Point], + proto_json=None, + ), + # same as before but with three lists + ExprTestCase( + expr=Point3D.zip(x=col("a"), y=col("b"), z=col("c")), + df=pd.DataFrame( + { + "a": [[1, 2], [3], []], + "b": [[4, 5, 6], [6, 8], [7, 9, 10]], + "c": [[8, 9], [10], [11]], + } ), + schema={"a": List[int], "b": List[int], "c": List[int]}, + display="""ZIP(Point3D, x=col("a"), y=col("b"), z=col("c"))""", + refs={"a", "b", "c"}, + eval_result=[[Point3D(1, 4, 8), A(2, 5, 9)], [A(3, 6, 10)], []], + expected_dtype=List[Point3D], + proto_json=None, + ), + ] + + for case in cases: + check_test_case(case) + + +def test_make_struct(): + cases = [ + # Make a struct + ExprTestCase( + expr=A.expr(x=col("a"), y=col("a") + col("b"), z="constant"), df=pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}), schema={"a": int, "b": int}, display="""STRUCT(x=col("a"), y=(col("a") + col("b")), z="constant")""", @@ -1162,17 +1449,10 @@ def test_make_struct(): ), # Make a nested struct ExprTestCase( - expr=( - make_struct( - { - "a": make_struct( - {"x": col("a"), "y": col("b"), "z": col("c")}, A - ), - "b": make_struct({"p": col("d"), "q": col("e")}, B), - "c": col("f"), - }, - Nested, - ) + expr=Nested.expr( + a=A.expr(x=col("a"), y=col("b"), z=col("c")), + b=B.expr(p=col("d"), q=col("e")), + c=col("f"), ), df=pd.DataFrame( { @@ -1207,6 +1487,11 @@ def test_make_struct(): for case in cases: check_test_case(case) + # construct a case that won't compile + expr = Point.zip(x=col("a"), y=col("b") * lit(2.2)) + with pytest.raises(Exception): + expr.typeof({"a": int, "b": int}) + def test_from_epoch(): cases = [ diff --git a/fennel/expr/test_invalid_expr.py b/fennel/expr/test_invalid_expr.py index 23e9d07cb..3b4697ada 100644 --- a/fennel/expr/test_invalid_expr.py +++ b/fennel/expr/test_invalid_expr.py @@ -97,7 +97,6 @@ def test_invalid_parse(): expr = col("a").str.parse(int) df = pd.DataFrame({"a": ['"A"', '"B"', '"C"']}) expr.eval(df, {"a": str}) - assert ( - str(e.value) - == "failed to evaluate expression: failed to convert polars array to fennel array for type 'Int'" + assert str(e.value).startswith( + "failed to evaluate expression: failed to convert polars array of type Int64 to fennel array for type 'Int' due to error" ) diff --git a/fennel/expr/visitor.py b/fennel/expr/visitor.py index b2cf16aa4..052ae63b0 100644 --- a/fennel/expr/visitor.py +++ b/fennel/expr/visitor.py @@ -12,6 +12,10 @@ ListHasNull, ListLen, ListNoop, + ListMap, + ListFilter, + ListAll, + ListAny, Literal, MakeStruct, Ref, @@ -38,6 +42,9 @@ NumToStr, Abs, Floor, + Sqrt, + Pow, + Log, StringNoop, StringParse, StringJsonExtract, @@ -57,11 +64,14 @@ _DateTime, DateTimeNoop, Now, + Repeat, + Zip, ) class Visitor(object): def visit(self, obj): + obj = obj.root if hasattr(obj, "root") else obj if isinstance(obj, Literal): ret = self.visitLiteral(obj) @@ -125,6 +135,12 @@ def visit(self, obj): elif isinstance(obj, Now): ret = self.visitNow(obj) + elif isinstance(obj, Zip): + ret = self.visitZip(obj) + + elif isinstance(obj, Repeat): + ret = self.visitRepeat(obj) + else: raise InvalidExprException("invalid expression type: %s" % obj) @@ -151,6 +167,12 @@ def visitIsNull(self, obj): def visitFillNull(self, obj): raise NotImplementedError + def visitRepeat(self, obj): + raise NotImplementedError() + + def visitZip(self, obj): + raise NotImplementedError() + def visitThen(self, obj): raise NotImplementedError @@ -206,7 +228,7 @@ def visitRef(self, obj): return str(obj) def visitVar(self, obj): - return str(obj) + return f'var("{obj.var}")' def visitUnary(self, obj): return "%s(%s)" % (obj.op, self.visit(obj.operand)) @@ -270,6 +292,14 @@ def visitNumber(self, obj): return "ABS(%s)" % self.visit(obj.operand) elif isinstance(obj.op, NumToStr): return f"TO_STRING({self.visit(obj.operand)})" + elif isinstance(obj.op, Sqrt): + return f"SQRT({self.visit(obj.operand)})" + elif isinstance(obj.op, Pow): + return ( + f"POW({self.visit(obj.operand)}, {self.visit(obj.op.exponent)})" + ) + elif isinstance(obj.op, Log): + return f"LOG({self.visit(obj.operand)}, base={obj.op.base})" else: raise InvalidExprException("invalid number operation: %s" % obj.op) @@ -349,6 +379,20 @@ def visitList(self, obj): return f"LEN({self.visit(obj.expr)})" elif isinstance(obj.op, ListHasNull): return f"HAS_NULL({self.visit(obj.expr)})" + elif isinstance(obj.op, ListMap): + return f'LIST_MAP({self.visit(obj.expr)}, "{obj.op.var}", {self.visit(obj.op.expr)})' + elif isinstance(obj.op, ListFilter): + return f"LIST_FILTER({self.visit(obj.expr)}, {self.visit(obj.op.func)})" + elif isinstance(obj.op, ListAll): + return ( + f"LIST_ALL({self.visit(obj.expr)}, {self.visit(obj.op.func)})" + ) + elif isinstance(obj.op, ListAny): + return ( + f"LIST_ANY({self.visit(obj.expr)}, {self.visit(obj.op.func)})" + ) + else: + raise InvalidExprException("invalid list operation: %s" % obj.op) def visitStruct(self, obj): if isinstance(obj.op, StructNoop): @@ -370,6 +414,15 @@ def visitDateTimeLiteral(self, obj): def visitNow(self, obj): return "NOW()" + def visitZip(self, obj): + kwargs = ", ".join( + [f"{k}={self.visit(v)}" for k, v in obj.fields.items()] + ) + return f"ZIP({obj.struct_type.__name__}, {kwargs})" + + def visitRepeat(self, obj): + return f"REPEAT({self.visit(obj.value)}, {self.visit(obj.by)})" + class FetchReferences(Visitor): @@ -424,6 +477,27 @@ def visitOtherwise(self, obj): def visitNumber(self, obj): self.visit(obj.operand) + if isinstance(obj.op, Sqrt): + pass + elif isinstance(obj.op, Pow): + self.visit(obj.op.exponent) + elif isinstance(obj.op, Log): + pass + elif isinstance(obj.op, Floor): + pass + elif isinstance(obj.op, Round): + pass + elif isinstance(obj.op, Ceil): + pass + elif isinstance(obj.op, NumToStr): + pass + elif isinstance(obj.op, Abs): + pass + elif isinstance(obj.op, MathNoop): + pass + else: + raise InvalidExprException("invalid number operation: %s" % obj.op) + def visitString(self, obj): self.visit(obj.operand) if isinstance(obj.op, StrContains): @@ -473,3 +547,11 @@ def visitDateTimeLiteral(self, obj): def visitNow(self, obj): pass + + def visitRepeat(self, obj): + self.visit(obj.value) + self.visit(obj.by) + + def visitZip(self, obj): + for k, v in obj.fields.items(): + self.visit(v) diff --git a/fennel/gen/expression_pb2.py b/fennel/gen/expression_pb2.py index ad4239301..2fc06444d 100644 --- a/fennel/gen/expression_pb2.py +++ b/fennel/gen/expression_pb2.py @@ -15,7 +15,7 @@ import fennel.gen.schema_pb2 as schema__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x65xpression.proto\x12\x17\x66\x65nnel.proto.expression\x1a\x0cschema.proto\"9\n\x0b\x45valContext\x12\x19\n\x0cnow_col_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_now_col_name\"\xd4\x07\n\x04\x45xpr\x12+\n\x03ref\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.RefH\x00\x12<\n\x0cjson_literal\x18\x02 \x01(\x0b\x32$.fennel.proto.expression.JsonLiteralH\x00\x12/\n\x05unary\x18\x04 \x01(\x0b\x32\x1e.fennel.proto.expression.UnaryH\x00\x12-\n\x04\x63\x61se\x18\x05 \x01(\x0b\x32\x1d.fennel.proto.expression.CaseH\x00\x12\x31\n\x06\x62inary\x18\x06 \x01(\x0b\x32\x1f.fennel.proto.expression.BinaryH\x00\x12\x31\n\x06isnull\x18\x07 \x01(\x0b\x32\x1f.fennel.proto.expression.IsNullH\x00\x12\x35\n\x08\x66illnull\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.FillNullH\x00\x12\x32\n\x07list_fn\x18\t \x01(\x0b\x32\x1f.fennel.proto.expression.ListFnH\x00\x12\x32\n\x07math_fn\x18\n \x01(\x0b\x32\x1f.fennel.proto.expression.MathFnH\x00\x12\x36\n\tstruct_fn\x18\x0b \x01(\x0b\x32!.fennel.proto.expression.StructFnH\x00\x12\x32\n\x07\x64ict_fn\x18\x0c \x01(\x0b\x32\x1f.fennel.proto.expression.DictFnH\x00\x12\x36\n\tstring_fn\x18\r \x01(\x0b\x32!.fennel.proto.expression.StringFnH\x00\x12:\n\x0b\x64\x61tetime_fn\x18\x0e \x01(\x0b\x32#.fennel.proto.expression.DateTimeFnH\x00\x12\x44\n\x10\x64\x61tetime_literal\x18\x0f \x01(\x0b\x32(.fennel.proto.expression.DatetimeLiteralH\x00\x12:\n\x0bmake_struct\x18\x10 \x01(\x0b\x32#.fennel.proto.expression.MakeStructH\x00\x12\x38\n\nfrom_epoch\x18\x11 \x01(\x0b\x32\".fennel.proto.expression.FromEpochH\x00\x12+\n\x03var\x18\x12 \x01(\x0b\x32\x1c.fennel.proto.expression.VarH\x00\x12+\n\x03now\x18\x13 \x01(\x0b\x32\x1c.fennel.proto.expression.NowH\x00\x42\x06\n\x04node\"\x05\n\x03Now\"\x13\n\x03Var\x12\x0c\n\x04name\x18\x01 \x01(\t\"m\n\tFromEpoch\x12/\n\x08\x64uration\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x04unit\x18\x02 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"\xb3\x01\n\x0f\x44\x61tetimeLiteral\x12\x0c\n\x04year\x18\x01 \x01(\r\x12\r\n\x05month\x18\x02 \x01(\r\x12\x0b\n\x03\x64\x61y\x18\x03 \x01(\r\x12\x0c\n\x04hour\x18\x04 \x01(\r\x12\x0e\n\x06minute\x18\x05 \x01(\r\x12\x0e\n\x06second\x18\x06 \x01(\r\x12\x13\n\x0bmicrosecond\x18\x07 \x01(\r\x12\x33\n\x08timezone\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\xd1\x01\n\nMakeStruct\x12\x34\n\x0bstruct_type\x18\x01 \x01(\x0b\x32\x1f.fennel.proto.schema.StructType\x12?\n\x06\x66ields\x18\x02 \x03(\x0b\x32/.fennel.proto.expression.MakeStruct.FieldsEntry\x1aL\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr:\x02\x38\x01\"L\n\x0bJsonLiteral\x12\x0f\n\x07literal\x18\x01 \x01(\t\x12,\n\x05\x64type\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.schema.DataType\"\x13\n\x03Ref\x12\x0c\n\x04name\x18\x01 \x01(\t\"e\n\x05Unary\x12,\n\x02op\x18\x01 \x01(\x0e\x32 .fennel.proto.expression.UnaryOp\x12.\n\x07operand\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\x8f\x01\n\x06\x42inary\x12+\n\x04left\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12,\n\x05right\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12*\n\x02op\x18\x03 \x01(\x0e\x32\x1e.fennel.proto.expression.BinOp\"n\n\x04\x43\x61se\x12\x34\n\twhen_then\x18\x01 \x03(\x0b\x32!.fennel.proto.expression.WhenThen\x12\x30\n\totherwise\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"d\n\x08WhenThen\x12+\n\x04when\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x04then\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"8\n\x06IsNull\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"g\n\x08\x46illNull\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x04\x66ill\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\xeb\x04\n\x06ListOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12,\n\x03get\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.ExprH\x00\x12\x35\n\x08\x63ontains\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x12\x34\n\x08has_null\x18\x04 \x01(\x0b\x32 .fennel.proto.expression.HasNullH\x00\x12/\n\x03sum\x18\x05 \x01(\x0b\x32 .fennel.proto.expression.ListSumH\x00\x12/\n\x03min\x18\x06 \x01(\x0b\x32 .fennel.proto.expression.ListMinH\x00\x12/\n\x03max\x18\x07 \x01(\x0b\x32 .fennel.proto.expression.ListMaxH\x00\x12/\n\x03\x61ll\x18\x08 \x01(\x0b\x32 .fennel.proto.expression.ListAllH\x00\x12/\n\x03\x61ny\x18\t \x01(\x0b\x32 .fennel.proto.expression.ListAnyH\x00\x12\x31\n\x04mean\x18\n \x01(\x0b\x32!.fennel.proto.expression.ListMeanH\x00\x12\x35\n\x06\x66ilter\x18\x0b \x01(\x0b\x32#.fennel.proto.expression.ListFilterH\x00\x12/\n\x03map\x18\x0c \x01(\x0b\x32 .fennel.proto.expression.ListMapH\x00\x42\t\n\x07\x66n_type\"K\n\nListFilter\x12\x0b\n\x03var\x18\x01 \x01(\t\x12\x30\n\tpredicate\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"G\n\x07ListMap\x12\x0b\n\x03var\x18\x01 \x01(\t\x12/\n\x08map_expr\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\t\n\x07ListSum\"\t\n\x07ListMin\"\n\n\x08ListMean\"\t\n\x07ListMax\"\t\n\x07ListAll\"\t\n\x07ListAny\"\x05\n\x03Len\"\t\n\x07HasNull\":\n\x08\x43ontains\x12.\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"b\n\x06ListFn\x12+\n\x04list\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.ListOp\"\x89\x02\n\x06MathOp\x12/\n\x05round\x18\x01 \x01(\x0b\x32\x1e.fennel.proto.expression.RoundH\x00\x12+\n\x03\x61\x62s\x18\x02 \x01(\x0b\x32\x1c.fennel.proto.expression.AbsH\x00\x12-\n\x04\x63\x65il\x18\x03 \x01(\x0b\x32\x1d.fennel.proto.expression.CeilH\x00\x12/\n\x05\x66loor\x18\x04 \x01(\x0b\x32\x1e.fennel.proto.expression.FloorH\x00\x12\x36\n\tto_string\x18\x05 \x01(\x0b\x32!.fennel.proto.expression.ToStringH\x00\x42\t\n\x07\x66n_type\"\x1a\n\x05Round\x12\x11\n\tprecision\x18\x01 \x01(\x05\"\x05\n\x03\x41\x62s\"\x06\n\x04\x43\x65il\"\x07\n\x05\x46loor\"\n\n\x08ToString\"e\n\x06MathFn\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.MathOp\"&\n\x08StructOp\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x42\t\n\x07\x66n_type\"h\n\x08StructFn\x12-\n\x06struct\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12-\n\x02\x66n\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.StructOp\"m\n\x07\x44ictGet\x12,\n\x05\x66ield\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12\x34\n\rdefault_value\x18\x03 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\xa8\x01\n\x06\x44ictOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12/\n\x03get\x18\x02 \x01(\x0b\x32 .fennel.proto.expression.DictGetH\x00\x12\x35\n\x08\x63ontains\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x42\t\n\x07\x66n_type\"b\n\x06\x44ictFn\x12+\n\x04\x64ict\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.DictOp\"\x9c\x05\n\x08StringOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12\x33\n\x07tolower\x18\x02 \x01(\x0b\x32 .fennel.proto.expression.ToLowerH\x00\x12\x33\n\x07toupper\x18\x03 \x01(\x0b\x32 .fennel.proto.expression.ToUpperH\x00\x12\x35\n\x08\x63ontains\x18\x04 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x12\x39\n\nstartswith\x18\x05 \x01(\x0b\x32#.fennel.proto.expression.StartsWithH\x00\x12\x35\n\x08\x65ndswith\x18\x06 \x01(\x0b\x32!.fennel.proto.expression.EndsWithH\x00\x12\x31\n\x06\x63oncat\x18\x07 \x01(\x0b\x32\x1f.fennel.proto.expression.ConcatH\x00\x12\x35\n\x08strptime\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.StrptimeH\x00\x12:\n\x0bjson_decode\x18\t \x01(\x0b\x32#.fennel.proto.expression.JsonDecodeH\x00\x12/\n\x05split\x18\n \x01(\x0b\x32\x1e.fennel.proto.expression.SplitH\x00\x12<\n\x0cjson_extract\x18\x0b \x01(\x0b\x32$.fennel.proto.expression.JsonExtractH\x00\x12\x30\n\x06to_int\x18\x0c \x01(\x0b\x32\x1e.fennel.proto.expression.ToIntH\x00\x42\t\n\x07\x66n_type\"\x1c\n\x08Timezone\x12\x10\n\x08timezone\x18\x01 \x01(\t\":\n\nJsonDecode\x12,\n\x05\x64type\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.schema.DataType\"O\n\x08Strptime\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\t\n\x07ToLower\"\t\n\x07ToUpper\"8\n\nStartsWith\x12*\n\x03key\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"6\n\x08\x45ndsWith\x12*\n\x03key\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"6\n\x06\x43oncat\x12,\n\x05other\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"h\n\x08StringFn\x12-\n\x06string\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12-\n\x02\x66n\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.StringOp\"n\n\nDateTimeFn\x12/\n\x08\x64\x61tetime\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x02\x66n\x18\x02 \x01(\x0b\x32#.fennel.proto.expression.DateTimeOp\"\xea\x01\n\nDateTimeOp\x12/\n\x05since\x18\x01 \x01(\x0b\x32\x1e.fennel.proto.expression.SinceH\x00\x12:\n\x0bsince_epoch\x18\x02 \x01(\x0b\x32#.fennel.proto.expression.SinceEpochH\x00\x12\x35\n\x08strftime\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.StrftimeH\x00\x12-\n\x04part\x18\x04 \x01(\x0b\x32\x1d.fennel.proto.expression.PartH\x00\x42\t\n\x07\x66n_type\"f\n\x05Since\x12,\n\x05other\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x04unit\x18\x02 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"=\n\nSinceEpoch\x12/\n\x04unit\x18\x01 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"O\n\x08Strftime\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"l\n\x04Part\x12/\n\x04unit\x18\x01 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\x14\n\x05Split\x12\x0b\n\x03sep\x18\x01 \x01(\t\"\x1b\n\x0bJsonExtract\x12\x0c\n\x04path\x18\x01 \x01(\t\"\x07\n\x05ToInt*\x1b\n\x07UnaryOp\x12\x07\n\x03NEG\x10\x00\x12\x07\n\x03NOT\x10\x01*\x86\x01\n\x05\x42inOp\x12\x07\n\x03\x41\x44\x44\x10\x00\x12\x07\n\x03SUB\x10\x01\x12\x07\n\x03MUL\x10\x02\x12\x07\n\x03\x44IV\x10\x03\x12\x07\n\x03MOD\x10\x04\x12\r\n\tFLOOR_DIV\x10\x05\x12\x06\n\x02\x45Q\x10\x06\x12\x06\n\x02NE\x10\x07\x12\x06\n\x02GT\x10\x08\x12\x07\n\x03GTE\x10\t\x12\x06\n\x02LT\x10\n\x12\x07\n\x03LTE\x10\x0b\x12\x07\n\x03\x41ND\x10\x0c\x12\x06\n\x02OR\x10\r*\x83\x01\n\x08TimeUnit\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06SECOND\x10\x01\x12\n\n\x06MINUTE\x10\x02\x12\x08\n\x04HOUR\x10\x03\x12\x07\n\x03\x44\x41Y\x10\x04\x12\x08\n\x04WEEK\x10\x05\x12\t\n\x05MONTH\x10\x06\x12\x08\n\x04YEAR\x10\x07\x12\x0f\n\x0bMICROSECOND\x10\x08\x12\x0f\n\x0bMILLISECOND\x10\tb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x65xpression.proto\x12\x17\x66\x65nnel.proto.expression\x1a\x0cschema.proto\"i\n\x0b\x45valContext\x12\x19\n\x0cnow_col_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eindex_col_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0f\n\r_now_col_nameB\x11\n\x0f_index_col_name\"\xb4\x08\n\x04\x45xpr\x12+\n\x03ref\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.RefH\x00\x12<\n\x0cjson_literal\x18\x02 \x01(\x0b\x32$.fennel.proto.expression.JsonLiteralH\x00\x12/\n\x05unary\x18\x04 \x01(\x0b\x32\x1e.fennel.proto.expression.UnaryH\x00\x12-\n\x04\x63\x61se\x18\x05 \x01(\x0b\x32\x1d.fennel.proto.expression.CaseH\x00\x12\x31\n\x06\x62inary\x18\x06 \x01(\x0b\x32\x1f.fennel.proto.expression.BinaryH\x00\x12\x31\n\x06isnull\x18\x07 \x01(\x0b\x32\x1f.fennel.proto.expression.IsNullH\x00\x12\x35\n\x08\x66illnull\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.FillNullH\x00\x12\x32\n\x07list_fn\x18\t \x01(\x0b\x32\x1f.fennel.proto.expression.ListFnH\x00\x12\x32\n\x07math_fn\x18\n \x01(\x0b\x32\x1f.fennel.proto.expression.MathFnH\x00\x12\x36\n\tstruct_fn\x18\x0b \x01(\x0b\x32!.fennel.proto.expression.StructFnH\x00\x12\x32\n\x07\x64ict_fn\x18\x0c \x01(\x0b\x32\x1f.fennel.proto.expression.DictFnH\x00\x12\x36\n\tstring_fn\x18\r \x01(\x0b\x32!.fennel.proto.expression.StringFnH\x00\x12:\n\x0b\x64\x61tetime_fn\x18\x0e \x01(\x0b\x32#.fennel.proto.expression.DateTimeFnH\x00\x12\x44\n\x10\x64\x61tetime_literal\x18\x0f \x01(\x0b\x32(.fennel.proto.expression.DatetimeLiteralH\x00\x12:\n\x0bmake_struct\x18\x10 \x01(\x0b\x32#.fennel.proto.expression.MakeStructH\x00\x12\x38\n\nfrom_epoch\x18\x11 \x01(\x0b\x32\".fennel.proto.expression.FromEpochH\x00\x12+\n\x03var\x18\x12 \x01(\x0b\x32\x1c.fennel.proto.expression.VarH\x00\x12+\n\x03now\x18\x13 \x01(\x0b\x32\x1c.fennel.proto.expression.NowH\x00\x12+\n\x03zip\x18\x14 \x01(\x0b\x32\x1c.fennel.proto.expression.ZipH\x00\x12\x31\n\x06repeat\x18\x15 \x01(\x0b\x32\x1f.fennel.proto.expression.RepeatH\x00\x42\x06\n\x04node\"c\n\x06Repeat\x12+\n\x04\x65xpr\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12,\n\x05\x63ount\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\x05\n\x03Now\"\x13\n\x03Var\x12\x0c\n\x04name\x18\x01 \x01(\t\"m\n\tFromEpoch\x12/\n\x08\x64uration\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x04unit\x18\x02 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"\xb3\x01\n\x0f\x44\x61tetimeLiteral\x12\x0c\n\x04year\x18\x01 \x01(\r\x12\r\n\x05month\x18\x02 \x01(\r\x12\x0b\n\x03\x64\x61y\x18\x03 \x01(\r\x12\x0c\n\x04hour\x18\x04 \x01(\r\x12\x0e\n\x06minute\x18\x05 \x01(\r\x12\x0e\n\x06second\x18\x06 \x01(\r\x12\x13\n\x0bmicrosecond\x18\x07 \x01(\r\x12\x33\n\x08timezone\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\xd1\x01\n\nMakeStruct\x12\x34\n\x0bstruct_type\x18\x01 \x01(\x0b\x32\x1f.fennel.proto.schema.StructType\x12?\n\x06\x66ields\x18\x02 \x03(\x0b\x32/.fennel.proto.expression.MakeStruct.FieldsEntry\x1aL\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr:\x02\x38\x01\"\xc3\x01\n\x03Zip\x12\x34\n\x0bstruct_type\x18\x01 \x01(\x0b\x32\x1f.fennel.proto.schema.StructType\x12\x38\n\x06\x66ields\x18\x02 \x03(\x0b\x32(.fennel.proto.expression.Zip.FieldsEntry\x1aL\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr:\x02\x38\x01\"L\n\x0bJsonLiteral\x12\x0f\n\x07literal\x18\x01 \x01(\t\x12,\n\x05\x64type\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.schema.DataType\"\x13\n\x03Ref\x12\x0c\n\x04name\x18\x01 \x01(\t\"e\n\x05Unary\x12,\n\x02op\x18\x01 \x01(\x0e\x32 .fennel.proto.expression.UnaryOp\x12.\n\x07operand\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\x8f\x01\n\x06\x42inary\x12+\n\x04left\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12,\n\x05right\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12*\n\x02op\x18\x03 \x01(\x0e\x32\x1e.fennel.proto.expression.BinOp\"n\n\x04\x43\x61se\x12\x34\n\twhen_then\x18\x01 \x03(\x0b\x32!.fennel.proto.expression.WhenThen\x12\x30\n\totherwise\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"d\n\x08WhenThen\x12+\n\x04when\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x04then\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"8\n\x06IsNull\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"g\n\x08\x46illNull\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x04\x66ill\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\xeb\x04\n\x06ListOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12,\n\x03get\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.ExprH\x00\x12\x35\n\x08\x63ontains\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x12\x34\n\x08has_null\x18\x04 \x01(\x0b\x32 .fennel.proto.expression.HasNullH\x00\x12/\n\x03sum\x18\x05 \x01(\x0b\x32 .fennel.proto.expression.ListSumH\x00\x12/\n\x03min\x18\x06 \x01(\x0b\x32 .fennel.proto.expression.ListMinH\x00\x12/\n\x03max\x18\x07 \x01(\x0b\x32 .fennel.proto.expression.ListMaxH\x00\x12/\n\x03\x61ll\x18\x08 \x01(\x0b\x32 .fennel.proto.expression.ListAllH\x00\x12/\n\x03\x61ny\x18\t \x01(\x0b\x32 .fennel.proto.expression.ListAnyH\x00\x12\x31\n\x04mean\x18\n \x01(\x0b\x32!.fennel.proto.expression.ListMeanH\x00\x12\x35\n\x06\x66ilter\x18\x0b \x01(\x0b\x32#.fennel.proto.expression.ListFilterH\x00\x12/\n\x03map\x18\x0c \x01(\x0b\x32 .fennel.proto.expression.ListMapH\x00\x42\t\n\x07\x66n_type\"K\n\nListFilter\x12\x0b\n\x03var\x18\x01 \x01(\t\x12\x30\n\tpredicate\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"G\n\x07ListMap\x12\x0b\n\x03var\x18\x01 \x01(\t\x12/\n\x08map_expr\x18\x02 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\t\n\x07ListSum\"\t\n\x07ListMin\"\n\n\x08ListMean\"\t\n\x07ListMax\"\t\n\x07ListAll\"\t\n\x07ListAny\"\x05\n\x03Len\"\t\n\x07HasNull\":\n\x08\x43ontains\x12.\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"b\n\x06ListFn\x12+\n\x04list\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.ListOp\"\x92\x03\n\x06MathOp\x12/\n\x05round\x18\x01 \x01(\x0b\x32\x1e.fennel.proto.expression.RoundH\x00\x12+\n\x03\x61\x62s\x18\x02 \x01(\x0b\x32\x1c.fennel.proto.expression.AbsH\x00\x12-\n\x04\x63\x65il\x18\x03 \x01(\x0b\x32\x1d.fennel.proto.expression.CeilH\x00\x12/\n\x05\x66loor\x18\x04 \x01(\x0b\x32\x1e.fennel.proto.expression.FloorH\x00\x12\x36\n\tto_string\x18\x05 \x01(\x0b\x32!.fennel.proto.expression.ToStringH\x00\x12+\n\x03pow\x18\x06 \x01(\x0b\x32\x1c.fennel.proto.expression.PowH\x00\x12+\n\x03log\x18\x07 \x01(\x0b\x32\x1c.fennel.proto.expression.LogH\x00\x12-\n\x04sqrt\x18\x08 \x01(\x0b\x32\x1d.fennel.proto.expression.SqrtH\x00\x42\t\n\x07\x66n_type\"\x1a\n\x05Round\x12\x11\n\tprecision\x18\x01 \x01(\x05\"6\n\x03Pow\x12/\n\x08\x65xponent\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\x13\n\x03Log\x12\x0c\n\x04\x62\x61se\x18\x01 \x01(\x01\"\x06\n\x04Sqrt\"\x05\n\x03\x41\x62s\"\x06\n\x04\x43\x65il\"\x07\n\x05\x46loor\"\n\n\x08ToString\"e\n\x06MathFn\x12.\n\x07operand\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.MathOp\"&\n\x08StructOp\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x42\t\n\x07\x66n_type\"h\n\x08StructFn\x12-\n\x06struct\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12-\n\x02\x66n\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.StructOp\"m\n\x07\x44ictGet\x12,\n\x05\x66ield\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12\x34\n\rdefault_value\x18\x03 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"\xa8\x01\n\x06\x44ictOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12/\n\x03get\x18\x02 \x01(\x0b\x32 .fennel.proto.expression.DictGetH\x00\x12\x35\n\x08\x63ontains\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x42\t\n\x07\x66n_type\"b\n\x06\x44ictFn\x12+\n\x04\x64ict\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12+\n\x02\x66n\x18\x02 \x01(\x0b\x32\x1f.fennel.proto.expression.DictOp\"\x9c\x05\n\x08StringOp\x12+\n\x03len\x18\x01 \x01(\x0b\x32\x1c.fennel.proto.expression.LenH\x00\x12\x33\n\x07tolower\x18\x02 \x01(\x0b\x32 .fennel.proto.expression.ToLowerH\x00\x12\x33\n\x07toupper\x18\x03 \x01(\x0b\x32 .fennel.proto.expression.ToUpperH\x00\x12\x35\n\x08\x63ontains\x18\x04 \x01(\x0b\x32!.fennel.proto.expression.ContainsH\x00\x12\x39\n\nstartswith\x18\x05 \x01(\x0b\x32#.fennel.proto.expression.StartsWithH\x00\x12\x35\n\x08\x65ndswith\x18\x06 \x01(\x0b\x32!.fennel.proto.expression.EndsWithH\x00\x12\x31\n\x06\x63oncat\x18\x07 \x01(\x0b\x32\x1f.fennel.proto.expression.ConcatH\x00\x12\x35\n\x08strptime\x18\x08 \x01(\x0b\x32!.fennel.proto.expression.StrptimeH\x00\x12:\n\x0bjson_decode\x18\t \x01(\x0b\x32#.fennel.proto.expression.JsonDecodeH\x00\x12/\n\x05split\x18\n \x01(\x0b\x32\x1e.fennel.proto.expression.SplitH\x00\x12<\n\x0cjson_extract\x18\x0b \x01(\x0b\x32$.fennel.proto.expression.JsonExtractH\x00\x12\x30\n\x06to_int\x18\x0c \x01(\x0b\x32\x1e.fennel.proto.expression.ToIntH\x00\x42\t\n\x07\x66n_type\"\x1c\n\x08Timezone\x12\x10\n\x08timezone\x18\x01 \x01(\t\":\n\nJsonDecode\x12,\n\x05\x64type\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.schema.DataType\"O\n\x08Strptime\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\t\n\x07ToLower\"\t\n\x07ToUpper\"8\n\nStartsWith\x12*\n\x03key\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"6\n\x08\x45ndsWith\x12*\n\x03key\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"6\n\x06\x43oncat\x12,\n\x05other\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\"h\n\x08StringFn\x12-\n\x06string\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12-\n\x02\x66n\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.StringOp\"n\n\nDateTimeFn\x12/\n\x08\x64\x61tetime\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x02\x66n\x18\x02 \x01(\x0b\x32#.fennel.proto.expression.DateTimeOp\"\xea\x01\n\nDateTimeOp\x12/\n\x05since\x18\x01 \x01(\x0b\x32\x1e.fennel.proto.expression.SinceH\x00\x12:\n\x0bsince_epoch\x18\x02 \x01(\x0b\x32#.fennel.proto.expression.SinceEpochH\x00\x12\x35\n\x08strftime\x18\x03 \x01(\x0b\x32!.fennel.proto.expression.StrftimeH\x00\x12-\n\x04part\x18\x04 \x01(\x0b\x32\x1d.fennel.proto.expression.PartH\x00\x42\t\n\x07\x66n_type\"f\n\x05Since\x12,\n\x05other\x18\x01 \x01(\x0b\x32\x1d.fennel.proto.expression.Expr\x12/\n\x04unit\x18\x02 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"=\n\nSinceEpoch\x12/\n\x04unit\x18\x01 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\"O\n\x08Strftime\x12\x0e\n\x06\x66ormat\x18\x01 \x01(\t\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"l\n\x04Part\x12/\n\x04unit\x18\x01 \x01(\x0e\x32!.fennel.proto.expression.TimeUnit\x12\x33\n\x08timezone\x18\x02 \x01(\x0b\x32!.fennel.proto.expression.Timezone\"\x14\n\x05Split\x12\x0b\n\x03sep\x18\x01 \x01(\t\"\x1b\n\x0bJsonExtract\x12\x0c\n\x04path\x18\x01 \x01(\t\"\x07\n\x05ToInt*\x1b\n\x07UnaryOp\x12\x07\n\x03NEG\x10\x00\x12\x07\n\x03NOT\x10\x01*\x86\x01\n\x05\x42inOp\x12\x07\n\x03\x41\x44\x44\x10\x00\x12\x07\n\x03SUB\x10\x01\x12\x07\n\x03MUL\x10\x02\x12\x07\n\x03\x44IV\x10\x03\x12\x07\n\x03MOD\x10\x04\x12\r\n\tFLOOR_DIV\x10\x05\x12\x06\n\x02\x45Q\x10\x06\x12\x06\n\x02NE\x10\x07\x12\x06\n\x02GT\x10\x08\x12\x07\n\x03GTE\x10\t\x12\x06\n\x02LT\x10\n\x12\x07\n\x03LTE\x10\x0b\x12\x07\n\x03\x41ND\x10\x0c\x12\x06\n\x02OR\x10\r*\x83\x01\n\x08TimeUnit\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06SECOND\x10\x01\x12\n\n\x06MINUTE\x10\x02\x12\x08\n\x04HOUR\x10\x03\x12\x07\n\x03\x44\x41Y\x10\x04\x12\x08\n\x04WEEK\x10\x05\x12\t\n\x05MONTH\x10\x06\x12\x08\n\x04YEAR\x10\x07\x12\x0f\n\x0bMICROSECOND\x10\x08\x12\x0f\n\x0bMILLISECOND\x10\tb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -24,130 +24,144 @@ DESCRIPTOR._loaded_options = None _globals['_MAKESTRUCT_FIELDSENTRY']._loaded_options = None _globals['_MAKESTRUCT_FIELDSENTRY']._serialized_options = b'8\001' - _globals['_UNARYOP']._serialized_start=6246 - _globals['_UNARYOP']._serialized_end=6273 - _globals['_BINOP']._serialized_start=6276 - _globals['_BINOP']._serialized_end=6410 - _globals['_TIMEUNIT']._serialized_start=6413 - _globals['_TIMEUNIT']._serialized_end=6544 + _globals['_ZIP_FIELDSENTRY']._loaded_options = None + _globals['_ZIP_FIELDSENTRY']._serialized_options = b'8\001' + _globals['_UNARYOP']._serialized_start=6911 + _globals['_UNARYOP']._serialized_end=6938 + _globals['_BINOP']._serialized_start=6941 + _globals['_BINOP']._serialized_end=7075 + _globals['_TIMEUNIT']._serialized_start=7078 + _globals['_TIMEUNIT']._serialized_end=7209 _globals['_EVALCONTEXT']._serialized_start=59 - _globals['_EVALCONTEXT']._serialized_end=116 - _globals['_EXPR']._serialized_start=119 - _globals['_EXPR']._serialized_end=1099 - _globals['_NOW']._serialized_start=1101 - _globals['_NOW']._serialized_end=1106 - _globals['_VAR']._serialized_start=1108 - _globals['_VAR']._serialized_end=1127 - _globals['_FROMEPOCH']._serialized_start=1129 - _globals['_FROMEPOCH']._serialized_end=1238 - _globals['_DATETIMELITERAL']._serialized_start=1241 - _globals['_DATETIMELITERAL']._serialized_end=1420 - _globals['_MAKESTRUCT']._serialized_start=1423 - _globals['_MAKESTRUCT']._serialized_end=1632 - _globals['_MAKESTRUCT_FIELDSENTRY']._serialized_start=1556 - _globals['_MAKESTRUCT_FIELDSENTRY']._serialized_end=1632 - _globals['_JSONLITERAL']._serialized_start=1634 - _globals['_JSONLITERAL']._serialized_end=1710 - _globals['_REF']._serialized_start=1712 - _globals['_REF']._serialized_end=1731 - _globals['_UNARY']._serialized_start=1733 - _globals['_UNARY']._serialized_end=1834 - _globals['_BINARY']._serialized_start=1837 - _globals['_BINARY']._serialized_end=1980 - _globals['_CASE']._serialized_start=1982 - _globals['_CASE']._serialized_end=2092 - _globals['_WHENTHEN']._serialized_start=2094 - _globals['_WHENTHEN']._serialized_end=2194 - _globals['_ISNULL']._serialized_start=2196 - _globals['_ISNULL']._serialized_end=2252 - _globals['_FILLNULL']._serialized_start=2254 - _globals['_FILLNULL']._serialized_end=2357 - _globals['_LISTOP']._serialized_start=2360 - _globals['_LISTOP']._serialized_end=2979 - _globals['_LISTFILTER']._serialized_start=2981 - _globals['_LISTFILTER']._serialized_end=3056 - _globals['_LISTMAP']._serialized_start=3058 - _globals['_LISTMAP']._serialized_end=3129 - _globals['_LISTSUM']._serialized_start=3131 - _globals['_LISTSUM']._serialized_end=3140 - _globals['_LISTMIN']._serialized_start=3142 - _globals['_LISTMIN']._serialized_end=3151 - _globals['_LISTMEAN']._serialized_start=3153 - _globals['_LISTMEAN']._serialized_end=3163 - _globals['_LISTMAX']._serialized_start=3165 - _globals['_LISTMAX']._serialized_end=3174 - _globals['_LISTALL']._serialized_start=3176 - _globals['_LISTALL']._serialized_end=3185 - _globals['_LISTANY']._serialized_start=3187 - _globals['_LISTANY']._serialized_end=3196 - _globals['_LEN']._serialized_start=3198 - _globals['_LEN']._serialized_end=3203 - _globals['_HASNULL']._serialized_start=3205 - _globals['_HASNULL']._serialized_end=3214 - _globals['_CONTAINS']._serialized_start=3216 - _globals['_CONTAINS']._serialized_end=3274 - _globals['_LISTFN']._serialized_start=3276 - _globals['_LISTFN']._serialized_end=3374 - _globals['_MATHOP']._serialized_start=3377 - _globals['_MATHOP']._serialized_end=3642 - _globals['_ROUND']._serialized_start=3644 - _globals['_ROUND']._serialized_end=3670 - _globals['_ABS']._serialized_start=3672 - _globals['_ABS']._serialized_end=3677 - _globals['_CEIL']._serialized_start=3679 - _globals['_CEIL']._serialized_end=3685 - _globals['_FLOOR']._serialized_start=3687 - _globals['_FLOOR']._serialized_end=3694 - _globals['_TOSTRING']._serialized_start=3696 - _globals['_TOSTRING']._serialized_end=3706 - _globals['_MATHFN']._serialized_start=3708 - _globals['_MATHFN']._serialized_end=3809 - _globals['_STRUCTOP']._serialized_start=3811 - _globals['_STRUCTOP']._serialized_end=3849 - _globals['_STRUCTFN']._serialized_start=3851 - _globals['_STRUCTFN']._serialized_end=3955 - _globals['_DICTGET']._serialized_start=3957 - _globals['_DICTGET']._serialized_end=4066 - _globals['_DICTOP']._serialized_start=4069 - _globals['_DICTOP']._serialized_end=4237 - _globals['_DICTFN']._serialized_start=4239 - _globals['_DICTFN']._serialized_end=4337 - _globals['_STRINGOP']._serialized_start=4340 - _globals['_STRINGOP']._serialized_end=5008 - _globals['_TIMEZONE']._serialized_start=5010 - _globals['_TIMEZONE']._serialized_end=5038 - _globals['_JSONDECODE']._serialized_start=5040 - _globals['_JSONDECODE']._serialized_end=5098 - _globals['_STRPTIME']._serialized_start=5100 - _globals['_STRPTIME']._serialized_end=5179 - _globals['_TOLOWER']._serialized_start=5181 - _globals['_TOLOWER']._serialized_end=5190 - _globals['_TOUPPER']._serialized_start=5192 - _globals['_TOUPPER']._serialized_end=5201 - _globals['_STARTSWITH']._serialized_start=5203 - _globals['_STARTSWITH']._serialized_end=5259 - _globals['_ENDSWITH']._serialized_start=5261 - _globals['_ENDSWITH']._serialized_end=5315 - _globals['_CONCAT']._serialized_start=5317 - _globals['_CONCAT']._serialized_end=5371 - _globals['_STRINGFN']._serialized_start=5373 - _globals['_STRINGFN']._serialized_end=5477 - _globals['_DATETIMEFN']._serialized_start=5479 - _globals['_DATETIMEFN']._serialized_end=5589 - _globals['_DATETIMEOP']._serialized_start=5592 - _globals['_DATETIMEOP']._serialized_end=5826 - _globals['_SINCE']._serialized_start=5828 - _globals['_SINCE']._serialized_end=5930 - _globals['_SINCEEPOCH']._serialized_start=5932 - _globals['_SINCEEPOCH']._serialized_end=5993 - _globals['_STRFTIME']._serialized_start=5995 - _globals['_STRFTIME']._serialized_end=6074 - _globals['_PART']._serialized_start=6076 - _globals['_PART']._serialized_end=6184 - _globals['_SPLIT']._serialized_start=6186 - _globals['_SPLIT']._serialized_end=6206 - _globals['_JSONEXTRACT']._serialized_start=6208 - _globals['_JSONEXTRACT']._serialized_end=6235 - _globals['_TOINT']._serialized_start=6237 - _globals['_TOINT']._serialized_end=6244 + _globals['_EVALCONTEXT']._serialized_end=164 + _globals['_EXPR']._serialized_start=167 + _globals['_EXPR']._serialized_end=1243 + _globals['_REPEAT']._serialized_start=1245 + _globals['_REPEAT']._serialized_end=1344 + _globals['_NOW']._serialized_start=1346 + _globals['_NOW']._serialized_end=1351 + _globals['_VAR']._serialized_start=1353 + _globals['_VAR']._serialized_end=1372 + _globals['_FROMEPOCH']._serialized_start=1374 + _globals['_FROMEPOCH']._serialized_end=1483 + _globals['_DATETIMELITERAL']._serialized_start=1486 + _globals['_DATETIMELITERAL']._serialized_end=1665 + _globals['_MAKESTRUCT']._serialized_start=1668 + _globals['_MAKESTRUCT']._serialized_end=1877 + _globals['_MAKESTRUCT_FIELDSENTRY']._serialized_start=1801 + _globals['_MAKESTRUCT_FIELDSENTRY']._serialized_end=1877 + _globals['_ZIP']._serialized_start=1880 + _globals['_ZIP']._serialized_end=2075 + _globals['_ZIP_FIELDSENTRY']._serialized_start=1801 + _globals['_ZIP_FIELDSENTRY']._serialized_end=1877 + _globals['_JSONLITERAL']._serialized_start=2077 + _globals['_JSONLITERAL']._serialized_end=2153 + _globals['_REF']._serialized_start=2155 + _globals['_REF']._serialized_end=2174 + _globals['_UNARY']._serialized_start=2176 + _globals['_UNARY']._serialized_end=2277 + _globals['_BINARY']._serialized_start=2280 + _globals['_BINARY']._serialized_end=2423 + _globals['_CASE']._serialized_start=2425 + _globals['_CASE']._serialized_end=2535 + _globals['_WHENTHEN']._serialized_start=2537 + _globals['_WHENTHEN']._serialized_end=2637 + _globals['_ISNULL']._serialized_start=2639 + _globals['_ISNULL']._serialized_end=2695 + _globals['_FILLNULL']._serialized_start=2697 + _globals['_FILLNULL']._serialized_end=2800 + _globals['_LISTOP']._serialized_start=2803 + _globals['_LISTOP']._serialized_end=3422 + _globals['_LISTFILTER']._serialized_start=3424 + _globals['_LISTFILTER']._serialized_end=3499 + _globals['_LISTMAP']._serialized_start=3501 + _globals['_LISTMAP']._serialized_end=3572 + _globals['_LISTSUM']._serialized_start=3574 + _globals['_LISTSUM']._serialized_end=3583 + _globals['_LISTMIN']._serialized_start=3585 + _globals['_LISTMIN']._serialized_end=3594 + _globals['_LISTMEAN']._serialized_start=3596 + _globals['_LISTMEAN']._serialized_end=3606 + _globals['_LISTMAX']._serialized_start=3608 + _globals['_LISTMAX']._serialized_end=3617 + _globals['_LISTALL']._serialized_start=3619 + _globals['_LISTALL']._serialized_end=3628 + _globals['_LISTANY']._serialized_start=3630 + _globals['_LISTANY']._serialized_end=3639 + _globals['_LEN']._serialized_start=3641 + _globals['_LEN']._serialized_end=3646 + _globals['_HASNULL']._serialized_start=3648 + _globals['_HASNULL']._serialized_end=3657 + _globals['_CONTAINS']._serialized_start=3659 + _globals['_CONTAINS']._serialized_end=3717 + _globals['_LISTFN']._serialized_start=3719 + _globals['_LISTFN']._serialized_end=3817 + _globals['_MATHOP']._serialized_start=3820 + _globals['_MATHOP']._serialized_end=4222 + _globals['_ROUND']._serialized_start=4224 + _globals['_ROUND']._serialized_end=4250 + _globals['_POW']._serialized_start=4252 + _globals['_POW']._serialized_end=4306 + _globals['_LOG']._serialized_start=4308 + _globals['_LOG']._serialized_end=4327 + _globals['_SQRT']._serialized_start=4329 + _globals['_SQRT']._serialized_end=4335 + _globals['_ABS']._serialized_start=4337 + _globals['_ABS']._serialized_end=4342 + _globals['_CEIL']._serialized_start=4344 + _globals['_CEIL']._serialized_end=4350 + _globals['_FLOOR']._serialized_start=4352 + _globals['_FLOOR']._serialized_end=4359 + _globals['_TOSTRING']._serialized_start=4361 + _globals['_TOSTRING']._serialized_end=4371 + _globals['_MATHFN']._serialized_start=4373 + _globals['_MATHFN']._serialized_end=4474 + _globals['_STRUCTOP']._serialized_start=4476 + _globals['_STRUCTOP']._serialized_end=4514 + _globals['_STRUCTFN']._serialized_start=4516 + _globals['_STRUCTFN']._serialized_end=4620 + _globals['_DICTGET']._serialized_start=4622 + _globals['_DICTGET']._serialized_end=4731 + _globals['_DICTOP']._serialized_start=4734 + _globals['_DICTOP']._serialized_end=4902 + _globals['_DICTFN']._serialized_start=4904 + _globals['_DICTFN']._serialized_end=5002 + _globals['_STRINGOP']._serialized_start=5005 + _globals['_STRINGOP']._serialized_end=5673 + _globals['_TIMEZONE']._serialized_start=5675 + _globals['_TIMEZONE']._serialized_end=5703 + _globals['_JSONDECODE']._serialized_start=5705 + _globals['_JSONDECODE']._serialized_end=5763 + _globals['_STRPTIME']._serialized_start=5765 + _globals['_STRPTIME']._serialized_end=5844 + _globals['_TOLOWER']._serialized_start=5846 + _globals['_TOLOWER']._serialized_end=5855 + _globals['_TOUPPER']._serialized_start=5857 + _globals['_TOUPPER']._serialized_end=5866 + _globals['_STARTSWITH']._serialized_start=5868 + _globals['_STARTSWITH']._serialized_end=5924 + _globals['_ENDSWITH']._serialized_start=5926 + _globals['_ENDSWITH']._serialized_end=5980 + _globals['_CONCAT']._serialized_start=5982 + _globals['_CONCAT']._serialized_end=6036 + _globals['_STRINGFN']._serialized_start=6038 + _globals['_STRINGFN']._serialized_end=6142 + _globals['_DATETIMEFN']._serialized_start=6144 + _globals['_DATETIMEFN']._serialized_end=6254 + _globals['_DATETIMEOP']._serialized_start=6257 + _globals['_DATETIMEOP']._serialized_end=6491 + _globals['_SINCE']._serialized_start=6493 + _globals['_SINCE']._serialized_end=6595 + _globals['_SINCEEPOCH']._serialized_start=6597 + _globals['_SINCEEPOCH']._serialized_end=6658 + _globals['_STRFTIME']._serialized_start=6660 + _globals['_STRFTIME']._serialized_end=6739 + _globals['_PART']._serialized_start=6741 + _globals['_PART']._serialized_end=6849 + _globals['_SPLIT']._serialized_start=6851 + _globals['_SPLIT']._serialized_end=6871 + _globals['_JSONEXTRACT']._serialized_start=6873 + _globals['_JSONEXTRACT']._serialized_end=6900 + _globals['_TOINT']._serialized_start=6902 + _globals['_TOINT']._serialized_end=6909 # @@protoc_insertion_point(module_scope) diff --git a/fennel/gen/expression_pb2.pyi b/fennel/gen/expression_pb2.pyi index e00682622..66da138fc 100644 --- a/fennel/gen/expression_pb2.pyi +++ b/fennel/gen/expression_pb2.pyi @@ -115,14 +115,20 @@ class EvalContext(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor NOW_COL_NAME_FIELD_NUMBER: builtins.int + INDEX_COL_NAME_FIELD_NUMBER: builtins.int now_col_name: builtins.str + index_col_name: builtins.str def __init__( self, *, now_col_name: builtins.str | None = ..., + index_col_name: builtins.str | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_now_col_name", b"_now_col_name", "now_col_name", b"now_col_name"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_now_col_name", b"_now_col_name", "now_col_name", b"now_col_name"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_index_col_name", b"_index_col_name", "_now_col_name", b"_now_col_name", "index_col_name", b"index_col_name", "now_col_name", b"now_col_name"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_index_col_name", b"_index_col_name", "_now_col_name", b"_now_col_name", "index_col_name", b"index_col_name", "now_col_name", b"now_col_name"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing_extensions.Literal["_index_col_name", b"_index_col_name"]) -> typing_extensions.Literal["index_col_name"] | None: ... + @typing.overload def WhichOneof(self, oneof_group: typing_extensions.Literal["_now_col_name", b"_now_col_name"]) -> typing_extensions.Literal["now_col_name"] | None: ... global___EvalContext = EvalContext @@ -149,6 +155,8 @@ class Expr(google.protobuf.message.Message): FROM_EPOCH_FIELD_NUMBER: builtins.int VAR_FIELD_NUMBER: builtins.int NOW_FIELD_NUMBER: builtins.int + ZIP_FIELD_NUMBER: builtins.int + REPEAT_FIELD_NUMBER: builtins.int @property def ref(self) -> global___Ref: ... @property @@ -186,6 +194,10 @@ class Expr(google.protobuf.message.Message): def var(self) -> global___Var: ... @property def now(self) -> global___Now: ... + @property + def zip(self) -> global___Zip: ... + @property + def repeat(self) -> global___Repeat: ... def __init__( self, *, @@ -207,13 +219,36 @@ class Expr(google.protobuf.message.Message): from_epoch: global___FromEpoch | None = ..., var: global___Var | None = ..., now: global___Now | None = ..., + zip: global___Zip | None = ..., + repeat: global___Repeat | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["binary", b"binary", "case", b"case", "datetime_fn", b"datetime_fn", "datetime_literal", b"datetime_literal", "dict_fn", b"dict_fn", "fillnull", b"fillnull", "from_epoch", b"from_epoch", "isnull", b"isnull", "json_literal", b"json_literal", "list_fn", b"list_fn", "make_struct", b"make_struct", "math_fn", b"math_fn", "node", b"node", "now", b"now", "ref", b"ref", "string_fn", b"string_fn", "struct_fn", b"struct_fn", "unary", b"unary", "var", b"var"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["binary", b"binary", "case", b"case", "datetime_fn", b"datetime_fn", "datetime_literal", b"datetime_literal", "dict_fn", b"dict_fn", "fillnull", b"fillnull", "from_epoch", b"from_epoch", "isnull", b"isnull", "json_literal", b"json_literal", "list_fn", b"list_fn", "make_struct", b"make_struct", "math_fn", b"math_fn", "node", b"node", "now", b"now", "ref", b"ref", "string_fn", b"string_fn", "struct_fn", b"struct_fn", "unary", b"unary", "var", b"var"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["node", b"node"]) -> typing_extensions.Literal["ref", "json_literal", "unary", "case", "binary", "isnull", "fillnull", "list_fn", "math_fn", "struct_fn", "dict_fn", "string_fn", "datetime_fn", "datetime_literal", "make_struct", "from_epoch", "var", "now"] | None: ... + def HasField(self, field_name: typing_extensions.Literal["binary", b"binary", "case", b"case", "datetime_fn", b"datetime_fn", "datetime_literal", b"datetime_literal", "dict_fn", b"dict_fn", "fillnull", b"fillnull", "from_epoch", b"from_epoch", "isnull", b"isnull", "json_literal", b"json_literal", "list_fn", b"list_fn", "make_struct", b"make_struct", "math_fn", b"math_fn", "node", b"node", "now", b"now", "ref", b"ref", "repeat", b"repeat", "string_fn", b"string_fn", "struct_fn", b"struct_fn", "unary", b"unary", "var", b"var", "zip", b"zip"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["binary", b"binary", "case", b"case", "datetime_fn", b"datetime_fn", "datetime_literal", b"datetime_literal", "dict_fn", b"dict_fn", "fillnull", b"fillnull", "from_epoch", b"from_epoch", "isnull", b"isnull", "json_literal", b"json_literal", "list_fn", b"list_fn", "make_struct", b"make_struct", "math_fn", b"math_fn", "node", b"node", "now", b"now", "ref", b"ref", "repeat", b"repeat", "string_fn", b"string_fn", "struct_fn", b"struct_fn", "unary", b"unary", "var", b"var", "zip", b"zip"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["node", b"node"]) -> typing_extensions.Literal["ref", "json_literal", "unary", "case", "binary", "isnull", "fillnull", "list_fn", "math_fn", "struct_fn", "dict_fn", "string_fn", "datetime_fn", "datetime_literal", "make_struct", "from_epoch", "var", "now", "zip", "repeat"] | None: ... global___Expr = Expr +@typing_extensions.final +class Repeat(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + EXPR_FIELD_NUMBER: builtins.int + COUNT_FIELD_NUMBER: builtins.int + @property + def expr(self) -> global___Expr: ... + @property + def count(self) -> global___Expr: ... + def __init__( + self, + *, + expr: global___Expr | None = ..., + count: global___Expr | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["count", b"count", "expr", b"expr"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["count", b"count", "expr", b"expr"]) -> None: ... + +global___Repeat = Repeat + @typing_extensions.final class Now(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -336,6 +371,45 @@ class MakeStruct(google.protobuf.message.Message): global___MakeStruct = MakeStruct +@typing_extensions.final +class Zip(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + @typing_extensions.final + class FieldsEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> global___Expr: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: global___Expr | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + + STRUCT_TYPE_FIELD_NUMBER: builtins.int + FIELDS_FIELD_NUMBER: builtins.int + @property + def struct_type(self) -> schema_pb2.StructType: ... + @property + def fields(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, global___Expr]: ... + def __init__( + self, + *, + struct_type: schema_pb2.StructType | None = ..., + fields: collections.abc.Mapping[builtins.str, global___Expr] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["struct_type", b"struct_type"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["fields", b"fields", "struct_type", b"struct_type"]) -> None: ... + +global___Zip = Zip + @typing_extensions.final class JsonLiteral(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -727,6 +801,9 @@ class MathOp(google.protobuf.message.Message): CEIL_FIELD_NUMBER: builtins.int FLOOR_FIELD_NUMBER: builtins.int TO_STRING_FIELD_NUMBER: builtins.int + POW_FIELD_NUMBER: builtins.int + LOG_FIELD_NUMBER: builtins.int + SQRT_FIELD_NUMBER: builtins.int @property def round(self) -> global___Round: ... @property @@ -737,6 +814,12 @@ class MathOp(google.protobuf.message.Message): def floor(self) -> global___Floor: ... @property def to_string(self) -> global___ToString: ... + @property + def pow(self) -> global___Pow: ... + @property + def log(self) -> global___Log: ... + @property + def sqrt(self) -> global___Sqrt: ... def __init__( self, *, @@ -745,10 +828,13 @@ class MathOp(google.protobuf.message.Message): ceil: global___Ceil | None = ..., floor: global___Floor | None = ..., to_string: global___ToString | None = ..., + pow: global___Pow | None = ..., + log: global___Log | None = ..., + sqrt: global___Sqrt | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["abs", b"abs", "ceil", b"ceil", "floor", b"floor", "fn_type", b"fn_type", "round", b"round", "to_string", b"to_string"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["abs", b"abs", "ceil", b"ceil", "floor", b"floor", "fn_type", b"fn_type", "round", b"round", "to_string", b"to_string"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["fn_type", b"fn_type"]) -> typing_extensions.Literal["round", "abs", "ceil", "floor", "to_string"] | None: ... + def HasField(self, field_name: typing_extensions.Literal["abs", b"abs", "ceil", b"ceil", "floor", b"floor", "fn_type", b"fn_type", "log", b"log", "pow", b"pow", "round", b"round", "sqrt", b"sqrt", "to_string", b"to_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["abs", b"abs", "ceil", b"ceil", "floor", b"floor", "fn_type", b"fn_type", "log", b"log", "pow", b"pow", "round", b"round", "sqrt", b"sqrt", "to_string", b"to_string"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["fn_type", b"fn_type"]) -> typing_extensions.Literal["round", "abs", "ceil", "floor", "to_string", "pow", "log", "sqrt"] | None: ... global___MathOp = MathOp @@ -767,6 +853,48 @@ class Round(google.protobuf.message.Message): global___Round = Round +@typing_extensions.final +class Pow(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + EXPONENT_FIELD_NUMBER: builtins.int + @property + def exponent(self) -> global___Expr: ... + def __init__( + self, + *, + exponent: global___Expr | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["exponent", b"exponent"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["exponent", b"exponent"]) -> None: ... + +global___Pow = Pow + +@typing_extensions.final +class Log(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + BASE_FIELD_NUMBER: builtins.int + base: builtins.float + def __init__( + self, + *, + base: builtins.float = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["base", b"base"]) -> None: ... + +global___Log = Log + +@typing_extensions.final +class Sqrt(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +global___Sqrt = Sqrt + @typing_extensions.final class Abs(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor diff --git a/fennel/internal_lib/schema/schema.py b/fennel/internal_lib/schema/schema.py index 21ae8c48b..d62b72426 100644 --- a/fennel/internal_lib/schema/schema.py +++ b/fennel/internal_lib/schema/schema.py @@ -241,6 +241,8 @@ def get_datatype(type_: Any) -> schema_proto.DataType: fields=fields, name=type_.__name__ ) ) + elif type_ is None: + return schema_proto.DataType(null_type=schema_proto.NullType()) raise ValueError(f"Cannot serialize type {type_}.") diff --git a/poetry.lock b/poetry.lock index ed5356788..e380a5ab6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -779,48 +779,48 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "fennel-data-lib" -version = "0.1.24" +version = "0.1.25" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "fennel_data_lib-0.1.24-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:810537b17cc9cf253c984d48d95b22438c4734b7a3035d2144f7b024f4521b58"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e1814938da9f6f82b9bce04bd95b3ba4b8f49ec4097054d46609e58c57b390"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dc9fbd4a6fdb71980569a82439ae7e0072981ca7454be5f5ef0834acd4cc8420"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab45451797311a94d2dbeff21cd7ad10bc925087f192c0e4a6a13aa96354e377"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80258a4b0189d0bdf4a271b15a4358dc031b76593732d4b4d2df6dfd72428d06"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a6810b1a1ba217a9a1b284122fff47ef21764e20de41e1d8e0fb8174e227a86"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:bdfb2a863b84b9238abdf5ae469bf1bbd87b5d6e3bea8defe24c83a13a7daf68"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d5d4c36eef520af2309ef07b328b6c72bf40bea6d481ce7a6bbb5d68edaef30b"}, - {file = "fennel_data_lib-0.1.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b8497f904144d86a62b3cb65f2e74799ca529ff25d30914490d71d8fa46abb46"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:54b0dda37d9e70c0de1f09cca3fd864ac622da35beef91bae81f7b8eaf1d3fa5"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ce9e776991550b911954209d021efb36444f7c81344c0ccc8b2303d2db115ed"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:139f213cc2b4c655860d9367f3ff00ac941cd16865dbb4e274d0b165b6809155"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a8573aa1e6604281cd86c26274973c93c2a559e6b67215328c55081411decd2"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f966cfa25e8a1430390b593c0cebcf38f64d4f88ca856fd680837564cf33b963"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8e10fbe416723e120078d1c42ecf9f415cb0adfecbc5c1679f3f7db2b833fc"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:c54a8841ce202a2f9c1d823a1988a654e31bf1ee8ec994d9120a15e05be8aac6"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47cac3a552969d36f69544c87e16727af868024acee895934da0d5250a4008fc"}, - {file = "fennel_data_lib-0.1.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:850e1a9e16f0a769610289a3f16020be81429b1d6a9e34062e800aace5a88122"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47b19869c1338f51fd4cd749ced952cda3b6596c5777eb66eaff5a068fd82acd"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:077df1687e89caec85ce1f395cb786e48a9edc601fd24bf4c12ccab3485087a8"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0374562846d4e90f7844c8a28ed2f986594a92dfe9cfb6d8298656ef94dc76e2"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9a6f14ff4a934c9834ba3d3e8c1aa999c16ca11acbd9cbc1a42932c25075c6"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be9d674efb45d6b8d94f7b7452135622048a67df5265d95dab35979476d3ca49"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1393db53e323097ce7d4f044de64cac94fba44b457131815a15a992d195127cc"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c9a3715913b42a1b4130b44d45e292630907cb4564acfc09a3dc8453bce45431"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4b993af888b29e074cddbac59f8a207a26c2acaabd5fc9ee16c68abf95879c81"}, - {file = "fennel_data_lib-0.1.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad5bec6bf17e0465cc3e0507700ec03869d848ab237d06175c0462aacdb74085"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3a927a88262ee0c93909969851a9c958ecea8e0d2757cdfe73276b5f90652c3a"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3dcd9a6bae8984714b87926c90552505f4442c70175734595c1c3582384194d"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad468415a888b5695cf186655819de2973c1744d0839f24a389e192d3c525f5a"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:54a597752ee872dd4c1523511d8933d4880a7eab9528c1c2b896059c6aa6bf3e"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ec997610b43af6eb570c9e8f13c5a1de45f7454dca26f6a9ce80a88a3728d6b"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cebdc9e295b2382e32b413129d2480da22f72b98c6253619e4a21c4173fa7f1"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:498c3bbef1ec8f7e760ab1ba20074f256c2b37f90f2faa5e6360b30112535255"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f66a6c2d7f20d4ba4d47c13adcbeefe8897ad6579b0d1817c4928e2e57627531"}, - {file = "fennel_data_lib-0.1.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a5ca35ca16994ede332419331fc524704432afc1c5ef66afd84fa2c57da6bb3"}, - {file = "fennel_data_lib-0.1.24.tar.gz", hash = "sha256:0fe65710e04be1399c106ff593eaa9f4b57f5f511579ff82fec97b320d85f4d1"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1400b5f3f3d525d883779d26aac4702378db5b4a8acc6096f2abbf03675af4c6"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2eb6ebf78093e95f9e6fbc183dc37b068659a2737c0a1eab3104cbc3d7a57f7"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b1e3e647ad7e52cc76375fc1a6e16a90be9e4e6d4af1f188ddfe08d6b06f376"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca5f08611deed275ca4f7bf11a657a28ecc4eac6b28909a43261f9f076ab7318"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33beaed0bafa19a7ff9d2e238e208c787f9cad58f772e974c0b3964974d7c0df"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ebc93b10b63d87cecb14bb9adc2ed887989f2b505b11f72ebfe36136cb68ad2"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:8fdd358dee6a1151bd0e1a2c8ea3658b8fd0c2c09f90decfc98d2032cddc1d75"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:67feb21127dcb175d75ef257f35d6646e8fb220aa08bfb6d6d5ea7dd42fc3fa9"}, + {file = "fennel_data_lib-0.1.25-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2faf3ef2cb180681f36359f680fb7df4759412ae10f6bf533a68a375cf49ad18"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e4acb6e7070e52694d27329ca0e30394e5a2d1adf8f270c8f96b5e9c11cd8bb4"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88cf52f24d91edc3a04aaddd0e79dd3aad35f8121d40719ff19a1a3b3c9774c1"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f26555f437a2c64807e101c55b3d6c60e4b1558a774a6792ad27643a2b6305dc"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c75c0ef4a91a2ca2fd6482aeb8bd951ac2aa034f0ed4a95e1237dbda3ad4c3d2"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:871484118f6a851f9a1a7a1487a490ee53a2990eff37665bdf3b49c13d2eb218"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0915d044846f4b8671cd06b26a043cc04aa11d7201275c11bf6cd3b61ed8e670"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:eaa7641d27f56cfbf39e20e340e72ef424bb43c645cad7c5c9146b63695ea022"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d96c184432bec2659f370e01f0b9b40fd100adbc446f58032bc5984933206c84"}, + {file = "fennel_data_lib-0.1.25-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4176b1f5982bef56f73c5ff87952755f6ac9e323f1a183b6333dc6cb5d102c6"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fe99900e98f8e2f3fbe5514ed0c469fd284b7333e34c7d0e71c4dd580d3445fa"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13e2d698086214c6acd91b524bbfbcd674c73a2f9f765a348878738bcbcfe2fd"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf699de573eaec451d8772e7f78a4790b1f2f622ab3f09470ff048d6ce98717c"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03aadebe7f5ff49a5528daf44409641a88148822ea4102420fe2db1e6428fb34"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ff6efa8c4381bedc40e0acc2200ad795601ac4c491bc509eb9e177e3db8bf78"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b74f63236c1a7d15260a5146099c679ffca725ba4c68d297bfcf4ffc8271ecd1"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:832f87853c0f741c7f22beede8805c67dfe198d585f31aa028fab516bec73a17"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb2ca03345f56be681ff9cfe655fa452042fb7daec73e0222a7aa504451c5167"}, + {file = "fennel_data_lib-0.1.25-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d1aa9a6579e3522eeede64677badcf00c7b3c365df3a15bf5a8be2138ddfabf1"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd2a9dd606acd96fe861e28a3080b41f8cd1ca05c132662f284c074172962b0c"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3874ecc64585b2b993a9b5f4c72549e9f8d42490f6186a36cf7a82ce34012b02"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:777043aa1f0360b080352903c54c9d6e63ec779ea0ddbec3d457e6983dd24336"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e80106bc7e9821ca28c24a074d7361fd848e6326644e4b891af35b0d7ed15f7"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2af0e8d18d5295c973e9d61959d4d07bca49848e6b6c96e684dd37ae737ed54e"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74d4f3bbab20534b227db6b2c15fd8ea72ca3541d715168b6b8c34320aa9cf88"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:eba4ec03e2d8a4e1244bebc5cf7f9554ebea3d17e9547fa212f525ca0c133ad5"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dda353e838b6ef04adeeb1a0116aba623eab4b3dddacd7a38dea9cfb444c7e28"}, + {file = "fennel_data_lib-0.1.25-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9656746be7355876252fb4b8d808cadf14741d316878bd0d8da2149ef4ecd98f"}, + {file = "fennel_data_lib-0.1.25.tar.gz", hash = "sha256:9194b244928ba7c07acefb052ed75425fbe63a9803f0e5580702ff902f42af15"}, ] [[package]] @@ -3771,4 +3771,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "8b8f85fde3aaeb25f9dc5cda7264e90e32645fd7221f770bb90a9c8e1bbb6768" +content-hash = "a2fc7a796b70119c03404c978ca01393b6fd63cf84076be12826cc8ff35920c8" diff --git a/pyproject.toml b/pyproject.toml index ad0511f34..4281b861a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "fennel-ai" -version = "1.5.62" +version = "1.5.63" description = "The modern realtime feature engineering platform" authors = ["Fennel AI "] packages = [{ include = "fennel" }] @@ -20,7 +20,7 @@ pytest = "7.1.3" pytest-rerunfailures = "^13.0" sortedcontainers = "^2.4.0" typing-extensions = "^4.12.0" -fennel-data-lib = "0.1.24" +fennel-data-lib = "0.1.25" pyarrow = "^14.0.2" [tool.poetry.dev-dependencies] @@ -58,8 +58,6 @@ build-backend = "poetry.core.masonry.api" # sdist-directory = "python_package" # manifest-path = "../server/fennel_data_lib/Cargo.toml" - -# inspired from - https://github.com/pypa/pip/blob/main/pyproject.toml # inspired from - https://github.com/pypa/pip/blob/main/pyproject.toml # vendoring configuration