|
19 | 19 | from narwhals._expression_parsing import ( |
20 | 20 | ExprKind, |
21 | 21 | check_expressions_preserve_length, |
22 | | - is_expr, |
| 22 | + is_into_expr_eager, |
23 | 23 | is_scalar_like, |
24 | | - is_series, |
25 | 24 | ) |
26 | 25 | from narwhals._typing import Arrow, Pandas, _LazyAllowedImpl, _LazyFrameCollectImpl |
27 | 26 | from narwhals._utils import ( |
|
44 | 43 | supports_arrow_c_stream, |
45 | 44 | zip_strict, |
46 | 45 | ) |
47 | | -from narwhals.dependencies import is_numpy_array_1d, is_numpy_array_2d, is_pyarrow_table |
| 46 | +from narwhals.dependencies import is_numpy_array_2d, is_pyarrow_table |
48 | 47 | from narwhals.exceptions import ( |
49 | 48 | ColumnNotFoundError, |
50 | 49 | InvalidIntoExprError, |
51 | 50 | InvalidOperationError, |
52 | 51 | PerformanceWarning, |
53 | 52 | ) |
54 | | -from narwhals.functions import _from_dict_no_backend, _is_into_schema, col, new_series |
| 53 | +from narwhals.functions import _from_dict_no_backend, _is_into_schema |
55 | 54 | from narwhals.schema import Schema |
56 | 55 | from narwhals.series import Series |
57 | 56 | from narwhals.translate import to_native |
|
68 | 67 | from typing_extensions import Concatenate, ParamSpec, Self, TypeAlias |
69 | 68 |
|
70 | 69 | from narwhals._compliant import CompliantDataFrame, CompliantLazyFrame |
71 | | - from narwhals._compliant.typing import CompliantExprAny |
| 70 | + from narwhals._compliant.typing import CompliantExprAny, EagerNamespaceAny |
72 | 71 | from narwhals._translate import IntoArrowTable |
73 | 72 | from narwhals._typing import EagerAllowed, IntoBackend, LazyAllowed, Polars |
74 | | - from narwhals.expr import Expr |
75 | 73 | from narwhals.group_by import GroupBy, LazyGroupBy |
76 | 74 | from narwhals.typing import ( |
77 | 75 | AsofJoinStrategy, |
|
89 | 87 | SingleIndexSelector, |
90 | 88 | SizeUnit, |
91 | 89 | UniqueKeepStrategy, |
92 | | - _1DArray, |
93 | 90 | _2DArray, |
94 | 91 | ) |
95 | 92 |
|
@@ -151,21 +148,18 @@ def _flatten_and_extract( |
151 | 148 | # NOTE: Strings are interpreted as column names. |
152 | 149 | out_exprs = [] |
153 | 150 | out_kinds = [] |
154 | | - ns = self.__narwhals_namespace__() |
155 | | - all_exprs = chain( |
156 | | - (self._parse_into_expr(x) for x in flatten(exprs)), |
157 | | - ( |
158 | | - self._parse_into_expr(expr).alias(alias) |
159 | | - for alias, expr in named_exprs.items() |
160 | | - ), |
161 | | - ) |
162 | | - for expr in all_exprs: |
163 | | - out_exprs.append(expr._to_compliant_expr(ns)) |
164 | | - out_kinds.append(ExprKind.from_expr(expr)) |
| 151 | + for expr in flatten(exprs): |
| 152 | + compliant_expr = self._extract_compliant(expr) |
| 153 | + out_exprs.append(compliant_expr) |
| 154 | + out_kinds.append(ExprKind.from_into_expr(expr, str_as_lit=False)) |
| 155 | + for alias, expr in named_exprs.items(): |
| 156 | + compliant_expr = self._extract_compliant(expr).alias(alias) |
| 157 | + out_exprs.append(compliant_expr) |
| 158 | + out_kinds.append(ExprKind.from_into_expr(expr, str_as_lit=False)) |
165 | 159 | return out_exprs, out_kinds |
166 | 160 |
|
167 | 161 | @abstractmethod |
168 | | - def _parse_into_expr(self, arg: Any) -> Expr: |
| 162 | + def _extract_compliant(self, arg: Any) -> Any: |
169 | 163 | raise NotImplementedError |
170 | 164 |
|
171 | 165 | def _extract_compliant_frame(self, other: Self | Any, /) -> Any: |
@@ -482,15 +476,10 @@ class DataFrame(BaseFrame[DataFrameT]): |
482 | 476 | def _compliant(self) -> CompliantDataFrame[Any, Any, DataFrameT, Self]: |
483 | 477 | return self._compliant_frame |
484 | 478 |
|
485 | | - def _parse_into_expr(self, arg: Expr | Series[Any] | _1DArray | str) -> Expr: |
486 | | - if isinstance(arg, str): |
487 | | - return col(arg) |
488 | | - if is_numpy_array_1d(arg): |
489 | | - return new_series("", arg, backend=self.implementation)._to_expr() |
490 | | - if is_series(arg): |
491 | | - return arg._to_expr() |
492 | | - if is_expr(arg): |
493 | | - return arg |
| 479 | + def _extract_compliant(self, arg: Any) -> Any: |
| 480 | + if is_into_expr_eager(arg): |
| 481 | + plx: EagerNamespaceAny = self.__narwhals_namespace__() |
| 482 | + return plx.parse_into_expr(arg, str_as_lit=False) |
494 | 483 | raise InvalidIntoExprError.from_invalid_type(type(arg)) |
495 | 484 |
|
496 | 485 | @property |
@@ -2298,34 +2287,39 @@ class LazyFrame(BaseFrame[LazyFrameT]): |
2298 | 2287 | def _compliant(self) -> CompliantLazyFrame[Any, LazyFrameT, Self]: |
2299 | 2288 | return self._compliant_frame |
2300 | 2289 |
|
2301 | | - def _parse_into_expr(self, arg: Expr | str) -> Expr: |
2302 | | - if isinstance(arg, str): |
2303 | | - return col(arg) |
2304 | | - if is_expr(arg): |
2305 | | - if arg._metadata.n_orderable_ops: |
2306 | | - msg = ( |
2307 | | - "Order-dependent expressions are not supported for use in LazyFrame.\n\n" |
2308 | | - "Hint: To make the expression valid, use `.over` with `order_by` specified.\n\n" |
2309 | | - "For example, if you wrote `nw.col('price').cum_sum()` and you have a column\n" |
2310 | | - "`'date'` which orders your data, then replace:\n\n" |
2311 | | - " nw.col('price').cum_sum()\n\n" |
2312 | | - " with:\n\n" |
2313 | | - " nw.col('price').cum_sum().over(order_by='date')\n" |
2314 | | - " ^^^^^^^^^^^^^^^^^^^^^^\n\n" |
2315 | | - "See https://narwhals-dev.github.io/narwhals/concepts/order_dependence/." |
2316 | | - ) |
2317 | | - raise InvalidOperationError(msg) |
2318 | | - if arg._metadata.is_filtration: |
2319 | | - msg = ( |
2320 | | - "Length-changing expressions are not supported for use in LazyFrame, unless\n" |
2321 | | - "followed by an aggregation.\n\n" |
2322 | | - "Hints:\n" |
2323 | | - "- Instead of `lf.select(nw.col('a').head())`, use `lf.select('a').head()\n" |
2324 | | - "- Instead of `lf.select(nw.col('a').drop_nulls()).select(nw.sum('a'))`,\n" |
2325 | | - " use `lf.select(nw.col('a').drop_nulls().sum())\n" |
2326 | | - ) |
2327 | | - raise InvalidOperationError(msg) |
2328 | | - return arg |
| 2290 | + def _extract_compliant(self, arg: Any) -> Any: |
| 2291 | + from narwhals.expr import Expr |
| 2292 | + from narwhals.series import Series |
| 2293 | + |
| 2294 | + if isinstance(arg, Series): # pragma: no cover |
| 2295 | + msg = "Binary operations between Series and LazyFrame are not supported." |
| 2296 | + raise TypeError(msg) |
| 2297 | + if isinstance(arg, (Expr, str)): |
| 2298 | + if isinstance(arg, Expr): |
| 2299 | + if arg._metadata.n_orderable_ops: |
| 2300 | + msg = ( |
| 2301 | + "Order-dependent expressions are not supported for use in LazyFrame.\n\n" |
| 2302 | + "Hint: To make the expression valid, use `.over` with `order_by` specified.\n\n" |
| 2303 | + "For example, if you wrote `nw.col('price').cum_sum()` and you have a column\n" |
| 2304 | + "`'date'` which orders your data, then replace:\n\n" |
| 2305 | + " nw.col('price').cum_sum()\n\n" |
| 2306 | + " with:\n\n" |
| 2307 | + " nw.col('price').cum_sum().over(order_by='date')\n" |
| 2308 | + " ^^^^^^^^^^^^^^^^^^^^^^\n\n" |
| 2309 | + "See https://narwhals-dev.github.io/narwhals/concepts/order_dependence/." |
| 2310 | + ) |
| 2311 | + raise InvalidOperationError(msg) |
| 2312 | + if arg._metadata.is_filtration: |
| 2313 | + msg = ( |
| 2314 | + "Length-changing expressions are not supported for use in LazyFrame, unless\n" |
| 2315 | + "followed by an aggregation.\n\n" |
| 2316 | + "Hints:\n" |
| 2317 | + "- Instead of `lf.select(nw.col('a').head())`, use `lf.select('a').head()\n" |
| 2318 | + "- Instead of `lf.select(nw.col('a').drop_nulls()).select(nw.sum('a'))`,\n" |
| 2319 | + " use `lf.select(nw.col('a').drop_nulls().sum())\n" |
| 2320 | + ) |
| 2321 | + raise InvalidOperationError(msg) |
| 2322 | + return self.__narwhals_namespace__().parse_into_expr(arg, str_as_lit=False) |
2329 | 2323 | raise InvalidIntoExprError.from_invalid_type(type(arg)) |
2330 | 2324 |
|
2331 | 2325 | @property |
|
0 commit comments