diff --git a/altair/expr/core.py b/altair/expr/core.py index e0e9b11f9b..8c18b291ea 100644 --- a/altair/expr/core.py +++ b/altair/expr/core.py @@ -1,5 +1,4 @@ from ..utils import SchemaBase -from ..vegalite.v5.schema.core import ExprRef class DatumType(object): @@ -194,7 +193,7 @@ def __init__(self, name, args): super(FunctionExpressionReference, self).__init__(name=name, args=args) def __repr__(self): - args = ",".join(_js_repr(arg) for arg in self.args) + args = ",".join(str(arg) for arg in self.args) return "{name}({args})".format(name=self.name, args=args) diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index 6396b534b4..fb638e943e 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -15,6 +15,149 @@ from .display import renderers, VEGALITE_VERSION, VEGAEMBED_VERSION, VEGA_VERSION from .theme import themes +# ------------------------------------------------------------------------ +# ExprRef proxies +def __add__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("+", self.expr, other)) + + +def __radd__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("+", other, self.expr)) + + +def __sub__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("-", self.expr, other)) + + +def __rsub__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("-", other, self.expr)) + + +def __mul__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("*", self.expr, other)) + + +def __rmul__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("*", other, self.expr)) + + +def __truediv__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("/", self.expr, other)) + + +def __rtruediv__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("/", other, self.expr)) + + +def __mod__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("%", self.name, other)) + + +def __rmod__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("%", other, self.name)) + + +def __pow__(self, other): + # "**" Javascript operator is not supported in all browsers + return ExprRef(expr.core.FunctionExpressionReference("pow", (self.name, other))) + + +def __rpow__(self, other): + # "**" Javascript operator is not supported in all browsers + return ExprRef(expr.core.FunctionExpressionReference("pow", (other, self.name))) + + +def __neg__(self): + return ExprRef(expr.core.UnaryExpressionReference("-", self.name)) + + +def __pos__(self): + return ExprRef(expr.core.UnaryExpressionReference("+", self.name)) + + +# comparison operators + + +def __eq__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("===", self.name, other)) + + +def __ne__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("!==", self.name, other)) + + +def __gt__(self, other): + return ExprRef(expr.core.BinaryExpressionReference(">", self.name, other)) + + +def __lt__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("<", self.name, other)) + + +def __ge__(self, other): + return ExprRef(expr.core.BinaryExpressionReference(">=", self.name, other)) + + +def __le__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("<=", self.name, other)) + + +def __abs__(self): + return ExprRef(expr.core.FunctionExpressionReference("abs", (self.name,))) + + +# logical operators + + +def __and__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("&&", self.name, other)) + + +def __rand__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("&&", other, self.name)) + + +def __or__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("||", self.name, other)) + + +def __ror__(self, other): + return ExprRef(expr.core.BinaryExpressionReference("||", other, self.name)) + + +def __invert__(self): + return ExprRef(expr.core.UnaryExpressionReference("!", self.name)) + + +ExprRef.__add__ = __add__ +ExprRef.__radd__ = __radd__ +ExprRef.__sub__ = __sub__ +ExprRef.__rsub__ = __rsub__ +ExprRef.__mul__ = __mul__ +ExprRef.__rmul__ = __rmul__ +ExprRef.__truediv__ = __truediv__ +ExprRef.__rtruediv__ = __rtruediv__ +ExprRef.__div__ = __truediv__ +ExprRef.__rdiv__ = __rtruediv__ +ExprRef.__mod__ = __mod__ +ExprRef.__rmod__ = __rmod__ +ExprRef.__pow__ = __pow__ +ExprRef.__rpow__ = __rpow__ +ExprRef.__neg__ = __neg__ +ExprRef.__pos__ = __pos__ +ExprRef.__eq__ = __eq__ +ExprRef.__ne__ = __ne__ +ExprRef.__gt__ = __gt__ +ExprRef.__lt__ = __lt__ +ExprRef.__ge__ = __ge__ +ExprRef.__le__ = __le__ +ExprRef.__abs__ = __abs__ +ExprRef.__and__ = __and__ +ExprRef.__rand__ = __rand__ +ExprRef.__or__ = __or__ +ExprRef.__ror__ = __ror__ +ExprRef.__invert__ = __invert__ + # ------------------------------------------------------------------------ # Data Utilities diff --git a/altair/vegalite/v5/tests/test_api.py b/altair/vegalite/v5/tests/test_api.py index 450553f3c6..21514e817d 100644 --- a/altair/vegalite/v5/tests/test_api.py +++ b/altair/vegalite/v5/tests/test_api.py @@ -11,7 +11,7 @@ import pytest import pandas as pd -import altair.vegalite.v4 as alt +import altair.vegalite.v5 as alt try: import altair_saver # noqa: F401 @@ -956,3 +956,26 @@ def test_validate_dataset(): jsn = chart.to_json() assert jsn + + +def test_layer_marks_raise_width(): + import pandas as pd + + no_data = pd.DataFrame() + + c = alt.Chart(no_data).mark_circle().properties(width=100) + dct = (c + c).to_dict() + + assert dct["width"] == 100 + assert "width" not in dct["layer"][0].keys() + + +def test_expr_class_proxies(): + be = alt.datum.value / 1000 + year_slider = alt.binding_range(min=0, max=1000, step=5) + size_var = alt.variable(bind=year_slider, value=200, name="sample") + expr_div = size_var / 1000 + expr_pow = size_var ** 2 + 1 + + assert expr_div.expr == "sample / 1000" + assert expr_pow.expr == "pow(sample,2) + 1"