Repository: pola-rs/polars
File: py-polars/src/polars/functions/lit.py (Python)

Code before:
        return wrap_expr(plr.lit(value, allow_object, is_scalar=False))

    elif _check_for_numpy(value) and isinstance(value, np.ndarray):
        return lit(pl.Series("literal", value, dtype=dtype))

    elif _check_for_torch(value) and isinstance(value, torch.Tensor):
        return lit(pl.Series("literal", value.numpy(force=False), dtype=dtype))

    elif isinstance(value, (list, tuple)):
        return wrap_expr(
            plr.lit(
                pl.Series("literal", [value], dtype=dtype)._s,
                allow_object,
                is_scalar=True,
            )
        )

    elif isinstance(value, enum.Enum):
        return lit(value.value, dtype=dtype)

    if dtype:
        value_s = pl.Series("literal", [value]).cast(dtype)
        return wrap_expr(plr.lit(value_s._s, allow_object, is_scalar=True))

    if _check_for_numpy(value) and isinstance(value, np.generic):
        # note: the item() is a py-native datetime/timedelta when units < 'ns'
        if isinstance(item := value.item(), (date, datetime, timedelta)):
            return lit(item)

        # handle 'ns' units
        if isinstance(item, int) and hasattr(value, "dtype"):
            dtype_name = value.dtype.name
            if dtype_name.startswith("datetime64["):
                time_unit = dtype_name[len("datetime64[") : -1]  # type: ignore[assignment]
                return lit(item).cast(Datetime(time_unit))
            if dtype_name.startswith("timedelta64["):
                time_unit = dtype_name[len("timedelta64[") : -1]  # type: ignore[assignment]
                return lit(item).cast(Duration(time_unit))

        # handle known mappable values
        dtype = DataTypeMappings.NUMPY_KIND_AND_ITEMSIZE_TO_DTYPE.get(
            (value.dtype.kind, value.dtype.itemsize)
        )
        if dtype is not None:
            return lit(value, dtype=dtype)
    else:
        item = value

    return wrap_expr(plr.lit(item, allow_object, is_scalar=True))


Review comment (suggestion):
Shouldn't this object check go at the beginning of the function? If someone specifies `dtype=pl.Object`, that should be respected regardless of what `value` is--but all of the `if` statements above will capture the value and evaluate the result before we even see that the user wanted an object.

Code after:
        return wrap_expr(plr.lit(value, allow_object, is_scalar=False))

    elif _check_for_numpy(value) and isinstance(value, np.ndarray):
        return lit(pl.Series("literal", value, dtype=dtype))

    elif _check_for_torch(value) and isinstance(value, torch.Tensor):
        return lit(pl.Series("literal", value.numpy(force=False), dtype=dtype))

    elif isinstance(value, (list, tuple)):
        return wrap_expr(
            plr.lit(
                pl.Series("literal", [value], dtype=dtype)._s,
                allow_object,
                is_scalar=True,
            )
        )

    elif isinstance(value, enum.Enum):
        return lit(value.value, dtype=dtype)

    if dtype:
        value_s = (
            pl.Series("literal", [value], dtype=dtype)
            if dtype.is_object()
            else pl.Series("literal", [value]).cast(dtype)
        )
        return wrap_expr(plr.lit(value_s._s, allow_object, is_scalar=True))

    if _check_for_numpy(value) and isinstance(value, np.generic):
        # note: the item() is a py-native datetime/timedelta when units < 'ns'
        if isinstance(item := value.item(), (date, datetime, timedelta)):
            return lit(item)

        # handle 'ns' units
        if isinstance(item, int) and hasattr(value, "dtype"):
            dtype_name = value.dtype.name
            if dtype_name.startswith("datetime64["):
                time_unit = dtype_name[len("datetime64[") : -1]  # type: ignore[assignment]
                return lit(item).cast(Datetime(time_unit))
            if dtype_name.startswith("timedelta64["):
                time_unit = dtype_name[len("timedelta64[") : -1]  # type: ignore[assignment]
                return lit(item).cast(Duration(time_unit))

        # handle known mappable values
        dtype = DataTypeMappings.NUMPY_KIND_AND_ITEMSIZE_TO_DTYPE.get(
            (value.dtype.kind, value.dtype.itemsize)
        )
        if dtype is not None:
            return lit(value, dtype=dtype)
    else:
        item = value