Skip to content

Commit

Permalink
feat(python)!: Improve some error types and messages (#10470)
Browse files Browse the repository at this point in the history
Co-authored-by: Stijn de Gooijer <stijn@degooijer.io>
  • Loading branch information
aminalaee and stinodego committed Aug 16, 2023
1 parent 50f20b1 commit 2bc2de6
Show file tree
Hide file tree
Showing 55 changed files with 343 additions and 348 deletions.
4 changes: 2 additions & 2 deletions py-polars/polars/api.py
Expand Up @@ -54,10 +54,10 @@ def _create_namespace(

def namespace(ns_class: type[NS]) -> type[NS]:
if name in _reserved_namespaces:
raise AttributeError(f"Cannot override reserved namespace {name!r}")
raise AttributeError(f"cannot override reserved namespace {name!r}")
elif hasattr(cls, name):
warn(
f"Overriding existing custom namespace {name!r} (on {cls.__name__})",
f"Overriding existing custom namespace {name!r} (on {cls.__name__!r})",
UserWarning,
stacklevel=find_stacklevel(),
)
Expand Down
2 changes: 1 addition & 1 deletion py-polars/polars/config.py
Expand Up @@ -125,7 +125,7 @@ def __init__(self, *, restore_defaults: bool = False, **options: Any) -> None:
if not hasattr(self, opt) and not opt.startswith("set_"):
opt = f"set_{opt}"
if not hasattr(self, opt):
raise AttributeError(f"Config has no {opt!r} option")
raise AttributeError(f"`Config` has no option {opt!r}")
getattr(self, opt)(value)

def __enter__(self) -> Config:
Expand Down
10 changes: 6 additions & 4 deletions py-polars/polars/convert.py
Expand Up @@ -173,7 +173,7 @@ def from_dicts(
"""
if not data and not (schema or schema_overrides):
raise NoDataError("No rows. Cannot infer schema.")
raise NoDataError("no data, cannot infer schema")

return pl.DataFrame(
data,
Expand Down Expand Up @@ -448,7 +448,7 @@ def from_repr(tbl: str) -> DataFrame | Series:
if m is not None:
return _from_series_repr(m)

raise ValueError("No DataFrame or Series found in the given string")
raise ValueError("input string does not contain DataFrame or Series")


def from_numpy(
Expand Down Expand Up @@ -620,7 +620,7 @@ def from_arrow(
return pl.DataFrame(data=[], schema=schema, schema_overrides=schema_overrides)
else:
raise ValueError(
f"expected pyarrow Table, Array, or sequence of RecordBatches; got {type(data)}."
f"expected PyArrow Table, Array, or sequence of RecordBatches, got {type(data).__name__!r}"
)


Expand Down Expand Up @@ -724,4 +724,6 @@ def from_pandas(
include_index=include_index,
)
else:
raise ValueError(f"Expected pandas DataFrame or Series, got {type(data)}.")
raise ValueError(
f"expected pandas DataFrame or Series, got {type(data).__name__!r}"
)
122 changes: 60 additions & 62 deletions py-polars/polars/dataframe/frame.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions py-polars/polars/dataframe/groupby.py
Expand Up @@ -325,12 +325,12 @@ def apply(self, function: Callable[[DataFrame], DataFrame]) -> DataFrame:
elif isinstance(self.by, Iterable) and all(isinstance(c, str) for c in self.by):
by = list(self.by) # type: ignore[arg-type]
else:
raise TypeError("Cannot call `apply` when grouping by an expression.")
raise TypeError("cannot call `apply` when grouping by an expression")

if all(isinstance(c, str) for c in self.more_by):
by.extend(self.more_by) # type: ignore[arg-type]
else:
raise TypeError("Cannot call `apply` when grouping by an expression.")
raise TypeError("cannot call `apply` when grouping by an expression")

return self.df.__class__._from_pydf(
self.df._df.groupby_apply(by, function, self.maintain_order)
Expand Down
4 changes: 2 additions & 2 deletions py-polars/polars/datatypes/classes.py
Expand Up @@ -348,7 +348,7 @@ def __init__(

if self.time_unit not in ("ms", "us", "ns"):
raise ValueError(
f"Invalid time_unit; expected one of {{'ns','us','ms'}}, got {self.time_unit!r}"
f"invalid time_unit; expected one of {{'ns','us','ms'}}, got {self.time_unit!r}"
)

def __eq__(self, other: PolarsDataType) -> bool: # type: ignore[override]
Expand Down Expand Up @@ -390,7 +390,7 @@ def __init__(self, time_unit: TimeUnit = "us"):
self.time_unit = time_unit
if self.time_unit not in ("ms", "us", "ns"):
raise ValueError(
f"Invalid time_unit; expected one of {{'ns','us','ms'}}, got {self.time_unit!r}"
f"invalid time_unit; expected one of {{'ns','us','ms'}}, got {self.time_unit!r}"
)

def __eq__(self, other: PolarsDataType) -> bool: # type: ignore[override]
Expand Down
8 changes: 4 additions & 4 deletions py-polars/polars/datatypes/constructor.py
Expand Up @@ -59,7 +59,7 @@ def polars_type_to_constructor(

return _POLARS_TYPE_TO_CONSTRUCTOR[base_type]
except KeyError: # pragma: no cover
raise ValueError(f"Cannot construct PySeries for type {dtype}.") from None
raise ValueError(f"cannot construct PySeries for type {dtype!r}") from None


_NUMPY_TYPE_TO_CONSTRUCTOR = None
Expand Down Expand Up @@ -107,8 +107,8 @@ def numpy_values_and_dtype(
values = values.astype(np.int64)
else:
raise ValueError(
"Only 'D', 'ms', 'us', and 'ns' resolutions are supported when converting from numpy.datetime64. "
"Please cast to the closest supported unit before converting."
"only 'D', 'ms', 'us', and 'ns' resolutions are supported when converting from numpy.datetime64."
"\n\nPlease cast to the closest supported unit before converting"
)
return values, dtype

Expand All @@ -123,7 +123,7 @@ def numpy_type_to_constructor(dtype: type[np.dtype[Any]]) -> Callable[..., PySer
return PySeries.new_object
except NameError: # pragma: no cover
raise ImportError(
f"'numpy' is required to convert numpy dtype {dtype}."
f"'numpy' is required to convert numpy dtype {dtype!r}"
) from None


Expand Down
16 changes: 8 additions & 8 deletions py-polars/polars/datatypes/convert.py
Expand Up @@ -147,7 +147,7 @@ def _map_py_type_to_dtype(
else dtype(_map_py_type_to_dtype(nested)) # type: ignore[operator]
)

raise TypeError("Invalid type")
raise TypeError("invalid type")


def is_polars_dtype(dtype: Any, include_unknown: bool = False) -> bool:
Expand Down Expand Up @@ -352,7 +352,7 @@ def dtype_to_ctype(dtype: PolarsDataType) -> Any:
return DataTypeMappings.DTYPE_TO_CTYPE[dtype]
except KeyError: # pragma: no cover
raise NotImplementedError(
f"Conversion of polars data type {dtype} to C-type not implemented."
f"conversion of polars data type {dtype!r} to C-type not implemented"
) from None


Expand All @@ -363,7 +363,7 @@ def dtype_to_ffiname(dtype: PolarsDataType) -> str:
return DataTypeMappings.DTYPE_TO_FFINAME[dtype]
except KeyError: # pragma: no cover
raise NotImplementedError(
f"Conversion of polars data type {dtype} to FFI not implemented."
f"conversion of polars data type {dtype!r} to FFI not implemented"
) from None


Expand All @@ -374,7 +374,7 @@ def dtype_to_py_type(dtype: PolarsDataType) -> PythonDataType:
return DataTypeMappings.DTYPE_TO_PY_TYPE[dtype]
except KeyError: # pragma: no cover
raise NotImplementedError(
f"Conversion of polars data type {dtype} to Python type not implemented."
f"conversion of polars data type {dtype!r} to Python type not implemented"
) from None


Expand Down Expand Up @@ -431,7 +431,7 @@ def py_type_to_dtype(
if not raise_unmatched:
return None
raise ValueError(
f"Cannot infer dtype from '{data_type}' (type: {type(data_type).__name__})"
f"cannot infer dtype from {data_type!r} (type: {type(data_type).__name__!r})"
) from None


Expand All @@ -441,7 +441,7 @@ def py_type_to_arrow_type(dtype: PythonDataType) -> pa.lib.DataType:
return DataTypeMappings.PY_TYPE_TO_ARROW_TYPE[dtype]
except KeyError: # pragma: no cover
raise ValueError(
f"Cannot parse Python data type {dtype} into Arrow data type."
f"cannot parse Python data type {dtype!r} into Arrow data type"
) from None


Expand Down Expand Up @@ -490,7 +490,7 @@ def numpy_char_code_to_dtype(dtype_char: str) -> PolarsDataType:
]
except KeyError: # pragma: no cover
raise ValueError(
f"Cannot parse numpy data type {dtype} into Polars data type."
f"cannot parse numpy data type {dtype!r} into Polars data type"
) from None


Expand All @@ -515,6 +515,6 @@ def maybe_cast(
el = py_type(el) # type: ignore[call-arg, misc]
except Exception:
raise ValueError(
f"Cannot convert Python type {type(el)} to {dtype}"
f"cannot convert Python type {type(el).__name__!r} to {dtype!r}"
) from None
return el
4 changes: 2 additions & 2 deletions py-polars/polars/expr/binary.py
Expand Up @@ -177,7 +177,7 @@ def decode(self, encoding: TransferEncoding, *, strict: bool = True) -> Expr:
return wrap_expr(self._pyexpr.bin_base64_decode(strict))
else:
raise ValueError(
f"encoding must be one of {{'hex', 'base64'}}, got {encoding}"
f"encoding must be one of {{'hex', 'base64'}}, got {encoding!r}"
)

def encode(self, encoding: TransferEncoding) -> Expr:
Expand Down Expand Up @@ -224,5 +224,5 @@ def encode(self, encoding: TransferEncoding) -> Expr:
return wrap_expr(self._pyexpr.bin_base64_encode())
else:
raise ValueError(
f"encoding must be one of {{'hex', 'base64'}}, got {encoding}"
f"encoding must be one of {{'hex', 'base64'}}, got {encoding!r}"
)
2 changes: 1 addition & 1 deletion py-polars/polars/expr/datetime.py
Expand Up @@ -1322,7 +1322,7 @@ def epoch(self, time_unit: EpochTimeUnit = "us") -> Expr:
return wrap_expr(self._pyexpr).cast(Date).cast(Int32)
else:
raise ValueError(
f"time_unit must be one of {{'ns', 'us', 'ms', 's', 'd'}}, got {time_unit}"
f"time_unit must be one of {{'ns', 'us', 'ms', 's', 'd'}}, got {time_unit!r}"
)

def timestamp(self, time_unit: TimeUnit = "us") -> Expr:
Expand Down
42 changes: 21 additions & 21 deletions py-polars/polars/expr/expr.py
Expand Up @@ -134,9 +134,9 @@ def __str__(self) -> str:

def __bool__(self) -> NoReturn:
raise ValueError(
"Since Expr are lazy, the truthiness of an Expr is ambiguous. "
"Hint: use '&' or '|' to logically combine Expr, not 'and'/'or', and "
"use 'x.is_in([y,z])' instead of 'x in [y,z]' to check membership."
"since Expr are lazy, the truthiness of an Expr is ambiguous."
"\n\nHint: use '&' or '|' to logically combine Expr, not 'and'/'or', and"
" use 'x.is_in([y,z])' instead of 'x in [y,z]' to check membership"
)

def __abs__(self) -> Self:
Expand Down Expand Up @@ -880,13 +880,13 @@ def exclude(
exclude_dtypes.append(item)
else:
raise TypeError(
"Invalid input for `exclude`. Expected one or more `str`, "
f"`DataType`, or selector; found {type(item)!r} instead"
"invalid input for `exclude`. Expected one or more `str`,"
f"`DataType`, or selector; found {type(item).__name__!r} instead"
)

if exclude_cols and exclude_dtypes:
raise TypeError(
"Cannot exclude by both column name and dtype; use a selector instead"
"cannot exclude by both column name and dtype; use a selector instead"
)
elif exclude_dtypes:
return self._from_pyexpr(self._pyexpr.exclude_dtype(exclude_dtypes))
Expand Down Expand Up @@ -2470,13 +2470,13 @@ def fill_null(
"""
if value is not None and strategy is not None:
raise ValueError("cannot specify both 'value' and 'strategy'.")
raise ValueError("cannot specify both 'value' and 'strategy'")
elif value is None and strategy is None:
raise ValueError("must specify either a fill 'value' or 'strategy'")
elif strategy not in ("forward", "backward") and limit is not None:
raise ValueError(
"can only specify 'limit' when strategy is set to"
" 'backward' or 'forward'"
"can only specify 'limit' when strategy is set to "
"'backward' or 'forward'"
)

if value is not None:
Expand Down Expand Up @@ -8810,7 +8810,7 @@ def _remap_key_or_value_series(
)
if dtype != s.dtype:
raise ValueError(
f"Remapping values for map_dict could not be converted to {dtype}: found {s.dtype}"
f"remapping values for map_dict could not be converted to {dtype!r}: found {s.dtype!r}"
)
else:
# dtype was set, which should always be the case when:
Expand All @@ -8826,17 +8826,17 @@ def _remap_key_or_value_series(
)
if dtype != s.dtype:
raise ValueError(
f"Remapping {'keys' if is_keys else 'values'} for map_dict could not be converted to {dtype}: found {s.dtype}"
f"remapping {'keys' if is_keys else 'values'} for map_dict could not be converted to {dtype!r}: found {s.dtype!r}"
)

except OverflowError as exc:
if is_keys:
raise ValueError(
f"Remapping keys for map_dict could not be converted to {dtype}: {str(exc)}"
f"remapping keys for map_dict could not be converted to {dtype!r}: {str(exc)}"
) from exc
else:
raise ValueError(
f"Choose a more suitable output dtype for map_dict as remapping value could not be converted to {dtype}: {str(exc)}"
f"choose a more suitable output dtype for map_dict as remapping value could not be converted to {dtype!r}: {str(exc)}"
) from exc

if is_keys:
Expand All @@ -8847,7 +8847,7 @@ def _remap_key_or_value_series(
pass
else:
raise ValueError(
f"Remapping keys for map_dict could not be converted to {dtype} without losing values in the conversion."
f"remapping keys for map_dict could not be converted to {dtype!r} without losing values in the conversion"
)
else:
# values = remapping.values()
Expand All @@ -8857,7 +8857,7 @@ def _remap_key_or_value_series(
pass
else:
raise ValueError(
f"Remapping values for map_dict could not be converted to {dtype} without losing values in the conversion."
f"remapping values for map_dict could not be converted to {dtype!r} without losing values in the conversion"
)

return s
Expand Down Expand Up @@ -9151,28 +9151,28 @@ def _prepare_alpha(
"""Normalise EWM decay specification in terms of smoothing factor 'alpha'."""
if sum((param is not None) for param in (com, span, half_life, alpha)) > 1:
raise ValueError(
"Parameters 'com', 'span', 'half_life', and 'alpha' are mutually exclusive"
"parameters 'com', 'span', 'half_life', and 'alpha' are mutually exclusive"
)
if com is not None:
if com < 0.0:
raise ValueError(f"Require 'com' >= 0 (found {com})")
raise ValueError(f"require 'com' >= 0 (found {com!r})")
alpha = 1.0 / (1.0 + com)

elif span is not None:
if span < 1.0:
raise ValueError(f"Require 'span' >= 1 (found {span})")
raise ValueError(f"require 'span' >= 1 (found {span!r})")
alpha = 2.0 / (span + 1.0)

elif half_life is not None:
if half_life <= 0.0:
raise ValueError(f"Require 'half_life' > 0 (found {half_life})")
raise ValueError(f"require 'half_life' > 0 (found {half_life!r})")
alpha = 1.0 - math.exp(-math.log(2.0) / half_life)

elif alpha is None:
raise ValueError("One of 'com', 'span', 'half_life', or 'alpha' must be set")
raise ValueError("one of 'com', 'span', 'half_life', or 'alpha' must be set")

elif not (0 < alpha <= 1):
raise ValueError(f"Require 0 < 'alpha' <= 1 (found {alpha})")
raise ValueError(f"require 0 < 'alpha' <= 1 (found {alpha!r})")

return alpha

Expand Down
2 changes: 1 addition & 1 deletion py-polars/polars/expr/struct.py
Expand Up @@ -23,7 +23,7 @@ def __getitem__(self, item: str | int) -> Expr:
return wrap_expr(self._pyexpr.struct_field_by_index(item))
else:
raise ValueError(
f"expected type 'int | str', got {type(item).__name__} ({item!r})"
f"expected type 'int | str', got {type(item).__name__!r} ({item!r})"
)

def field(self, name: str) -> Expr:
Expand Down

0 comments on commit 2bc2de6

Please sign in to comment.