From 607529700a371b3ed2f67a942ef3fb491e6346ea Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Mon, 2 Nov 2020 14:14:18 +0000 Subject: [PATCH] refactor core/computation --- pandas/core/computation/align.py | 12 +++++++----- pandas/core/computation/eval.py | 11 +++++------ pandas/core/computation/expr.py | 17 ++++++++--------- pandas/core/computation/pytables.py | 16 ++++++++-------- pandas/core/computation/scope.py | 3 +-- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/pandas/core/computation/align.py b/pandas/core/computation/align.py index 82867cf9dcd29..8a8b0d564ea49 100644 --- a/pandas/core/computation/align.py +++ b/pandas/core/computation/align.py @@ -38,8 +38,7 @@ def _align_core_single_unary_op( def _zip_axes_from_type( typ: Type[FrameOrSeries], new_axes: Sequence[int] ) -> Dict[str, int]: - axes = {name: new_axes[i] for i, name in enumerate(typ._AXIS_ORDERS)} - return axes + return {name: new_axes[i] for i, name in enumerate(typ._AXIS_ORDERS)} def _any_pandas_objects(terms) -> bool: @@ -186,8 +185,11 @@ def reconstruct_object(typ, obj, axes, dtype): # The condition is to distinguish 0-dim array (returned in case of # scalar) and 1 element array # e.g. np.array(0) and np.array([0]) - if len(obj.shape) == 1 and len(obj) == 1: - if not isinstance(ret_value, np.ndarray): - ret_value = np.array([ret_value]).astype(res_t) + if ( + len(obj.shape) == 1 + and len(obj) == 1 + and not isinstance(ret_value, np.ndarray) + ): + ret_value = np.array([ret_value]).astype(res_t) return ret_value diff --git a/pandas/core/computation/eval.py b/pandas/core/computation/eval.py index b77204861f0a4..12f16343362e2 100644 --- a/pandas/core/computation/eval.py +++ b/pandas/core/computation/eval.py @@ -52,12 +52,11 @@ def _check_engine(engine: Optional[str]) -> str: # TODO: validate this in a more general way (thinking of future engines # that won't necessarily be import-able) # Could potentially be done on engine instantiation - if engine == "numexpr": - if not NUMEXPR_INSTALLED: - raise ImportError( - "'numexpr' is not installed or an unsupported version. Cannot use " - "engine='numexpr' for query/eval if 'numexpr' is not installed" - ) + if engine == "numexpr" and not NUMEXPR_INSTALLED: + raise ImportError( + "'numexpr' is not installed or an unsupported version. Cannot use " + "engine='numexpr' for query/eval if 'numexpr' is not installed" + ) return engine diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index 8c56f02c8d3cc..c971551a7f400 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -496,15 +496,14 @@ def _maybe_evaluate_binop( f"'{lhs.type}' and '{rhs.type}'" ) - if self.engine != "pytables": - if ( - res.op in CMP_OPS_SYMS - and getattr(lhs, "is_datetime", False) - or getattr(rhs, "is_datetime", False) - ): - # all date ops must be done in python bc numexpr doesn't work - # well with NaT - return self._maybe_eval(res, self.binary_ops) + if self.engine != "pytables" and ( + res.op in CMP_OPS_SYMS + and getattr(lhs, "is_datetime", False) + or getattr(rhs, "is_datetime", False) + ): + # all date ops must be done in python bc numexpr doesn't work + # well with NaT + return self._maybe_eval(res, self.binary_ops) if res.op in eval_in_python: # "in"/"not in" ops are always evaluated in python diff --git a/pandas/core/computation/pytables.py b/pandas/core/computation/pytables.py index dd622ed724e8f..6ec637a8b4845 100644 --- a/pandas/core/computation/pytables.py +++ b/pandas/core/computation/pytables.py @@ -378,14 +378,14 @@ def prune(self, klass): operand = self.operand operand = operand.prune(klass) - if operand is not None: - if issubclass(klass, ConditionBinOp): - if operand.condition is not None: - return operand.invert() - elif issubclass(klass, FilterBinOp): - if operand.filter is not None: - return operand.invert() - + if operand is not None and ( + issubclass(klass, ConditionBinOp) + and operand.condition is not None + or not issubclass(klass, ConditionBinOp) + and issubclass(klass, FilterBinOp) + and operand.filter is not None + ): + return operand.invert() return None diff --git a/pandas/core/computation/scope.py b/pandas/core/computation/scope.py index 2925f583bfc56..7a9b8caa985e3 100644 --- a/pandas/core/computation/scope.py +++ b/pandas/core/computation/scope.py @@ -144,8 +144,7 @@ def __init__( def __repr__(self) -> str: scope_keys = _get_pretty_string(list(self.scope.keys())) res_keys = _get_pretty_string(list(self.resolvers.keys())) - unicode_str = f"{type(self).__name__}(scope={scope_keys}, resolvers={res_keys})" - return unicode_str + return f"{type(self).__name__}(scope={scope_keys}, resolvers={res_keys})" @property def has_resolvers(self) -> bool: