|
25 | 25 | from typing_extensions import TypeAlias |
26 | 26 |
|
27 | 27 | from narwhals._utils import Implementation, Version |
28 | | - from narwhals.typing import IntoDType, NonNestedLiteral |
| 28 | + from narwhals.typing import IntoDType, PythonLiteral |
29 | 29 |
|
30 | 30 |
|
31 | 31 | Incomplete: TypeAlias = Any |
@@ -83,17 +83,46 @@ def func(df: PandasLikeDataFrame) -> list[PandasLikeSeries]: |
83 | 83 | context=self, |
84 | 84 | ) |
85 | 85 |
|
86 | | - def lit(self, value: NonNestedLiteral, dtype: IntoDType | None) -> PandasLikeExpr: |
| 86 | + def lit(self, value: PythonLiteral, dtype: IntoDType | None) -> PandasLikeExpr: |
87 | 87 | def _lit_pandas_series(df: PandasLikeDataFrame) -> PandasLikeSeries: |
88 | | - pandas_series = self._series.from_iterable( |
| 88 | + if isinstance(value, (list, tuple, dict)): |
| 89 | + try: |
| 90 | + import pandas as pd # ignore-banned-import |
| 91 | + import pyarrow as pa # ignore-banned-import |
| 92 | + except ImportError as exc: # pragma: no cover |
| 93 | + msg = ( |
| 94 | + "Nested structures require pyarrow to be installed for pandas backend. " |
| 95 | + "Please install pyarrow: pip install pyarrow" |
| 96 | + ) |
| 97 | + raise ImportError(msg) from exc |
| 98 | + |
| 99 | + from narwhals._arrow.utils import ( |
| 100 | + narwhals_to_native_dtype as _to_arrow_dtype, |
| 101 | + ) |
| 102 | + |
| 103 | + array_value = list(value) if isinstance(value, tuple) else value |
| 104 | + pa_dtype = _to_arrow_dtype(dtype, self._version) if dtype else None |
| 105 | + pa_array = pa.array([array_value], type=pa_dtype) # type: ignore[arg-type, list-item] |
| 106 | + |
| 107 | + # Use ArrowExtensionArray to avoid pandas unpacking the nested structure |
| 108 | + ns = self._implementation.to_native_namespace() |
| 109 | + pandas_series_native = ns.Series( |
| 110 | + pd.arrays.ArrowExtensionArray(pa_array), # type: ignore[attr-defined] |
| 111 | + name="literal", |
| 112 | + index=df._native_frame.index[0:1], |
| 113 | + ) |
| 114 | + |
| 115 | + return self._series.from_native(pandas_series_native, context=self) |
| 116 | + |
| 117 | + pandas_like_series = self._series.from_iterable( |
89 | 118 | data=[value], |
90 | 119 | name="literal", |
91 | 120 | index=df._native_frame.index[0:1], |
92 | 121 | context=self, |
93 | 122 | ) |
94 | 123 | if dtype: |
95 | | - return pandas_series.cast(dtype) |
96 | | - return pandas_series |
| 124 | + return pandas_like_series.cast(dtype) |
| 125 | + return pandas_like_series |
97 | 126 |
|
98 | 127 | return PandasLikeExpr( |
99 | 128 | lambda df: [_lit_pandas_series(df)], |
|
0 commit comments