From ce7f3f0d98b83ffad936d370355a1c3ce13a3fa1 Mon Sep 17 00:00:00 2001 From: rjzamora Date: Tue, 23 Jan 2024 08:20:55 -0800 Subject: [PATCH] remove Expr._required_attribute --- dask_expr/_core.py | 18 ++++-------------- dask_expr/_expr.py | 35 ----------------------------------- dask_expr/_reductions.py | 9 ++++----- 3 files changed, 8 insertions(+), 54 deletions(-) diff --git a/dask_expr/_core.py b/dask_expr/_core.py index 67f70a8bf..72e8cc1ba 100644 --- a/dask_expr/_core.py +++ b/dask_expr/_core.py @@ -39,18 +39,6 @@ def __init__(self, *args, **kwargs): assert not kwargs, kwargs operands = [_unpack_collections(o) for o in operands] self.operands = operands - if self._required_attribute: - dep = next(iter(self.dependencies()))._meta - if not hasattr(dep, self._required_attribute): - # Raise a ValueError instead of AttributeError to - # avoid infinite recursion - raise ValueError(f"{dep} has no attribute {self._required_attribute}") - - @property - def _required_attribute(self) -> str: - # Specify if the first `dependency` must support - # a specific attribute for valid behavior. - return None def __str__(self): s = ", ".join( @@ -407,8 +395,8 @@ def __getattr__(self, key): try: return object.__getattribute__(self, key) except AttributeError as err: - if key == "_meta": - # Avoid a recursive loop if/when `self._meta` + if key.startswith("_meta"): + # Avoid a recursive loop if/when `self._meta*` # produces an `AttributeError` raise RuntimeError( f"Failed to generate metadata for {self}. " @@ -422,6 +410,8 @@ def __getattr__(self, key): if key in _parameters: idx = _parameters.index(key) return self.operands[idx] + if is_dataframe_like(self._meta) and key in self._meta.columns: + return self[key] link = "https://github.com/dask-contrib/dask-expr/blob/main/README.md#api-coverage" raise AttributeError( diff --git a/dask_expr/_expr.py b/dask_expr/_expr.py index 1b56800f6..5d6e79aeb 100644 --- a/dask_expr/_expr.py +++ b/dask_expr/_expr.py @@ -88,35 +88,6 @@ def optimize(self, **kwargs): def __hash__(self): return hash(self._name) - def __getattr__(self, key): - try: - return object.__getattribute__(self, key) - except AttributeError as err: - if key == "_meta": - # Avoid a recursive loop if/when `self._meta` - # produces an `AttributeError` - raise RuntimeError( - f"Failed to generate metadata for {self}. " - "This operation may not be supported by the current backend." - ) - - # Allow operands to be accessed as attributes - # as long as the keys are not already reserved - # by existing methods/properties - _parameters = type(self)._parameters - if key in _parameters: - idx = _parameters.index(key) - return self.operands[idx] - if is_dataframe_like(self._meta) and key in self._meta.columns: - return self[key] - - link = "https://github.com/dask-contrib/dask-expr/blob/main/README.md#api-coverage" - raise AttributeError( - f"{err}\n\n" - "This often means that you are attempting to use an unsupported " - f"API function. Current API coverage is documented here: {link}." - ) - @property def index(self): return Index(self) @@ -493,12 +464,6 @@ class Blockwise(Expr): _projection_passthrough = False _filter_passthrough = False - @property - def _required_attribute(self): - if isinstance(self.operation, type(M.method_caller)): - return self.operation.method - return None - @functools.cached_property def _meta(self): args = [op._meta if isinstance(op, Expr) else op for op in self._args] diff --git a/dask_expr/_reductions.py b/dask_expr/_reductions.py index 7a87d5c3c..ff0c6989f 100644 --- a/dask_expr/_reductions.py +++ b/dask_expr/_reductions.py @@ -857,19 +857,19 @@ class IdxMin(Reduction): reduction_chunk = idxmaxmin_chunk reduction_combine = idxmaxmin_combine reduction_aggregate = idxmaxmin_agg - _required_attribute = "idxmin" + _reduction_attribute = "idxmin" @property def chunk_kwargs(self): return dict( skipna=self.skipna, - fn=self._required_attribute, + fn=self._reduction_attribute, numeric_only=self.numeric_only, ) @property def combine_kwargs(self): - return dict(skipna=self.skipna, fn=self._required_attribute) + return dict(skipna=self.skipna, fn=self._reduction_attribute) @property def aggregate_kwargs(self): @@ -877,7 +877,7 @@ def aggregate_kwargs(self): class IdxMax(IdxMin): - _required_attribute = "idxmax" + _reduction_attribute = "idxmax" class Cov(Reduction): @@ -961,7 +961,6 @@ def _simplify_up(self, parent, dependents): class NBytes(Reduction): # Only supported for Series objects reduction_aggregate = sum - _required_attribute = "nbytes" @staticmethod def reduction_chunk(ser):