Skip to content

Commit e2f0b56

Browse files
committed
Merge pull request #6448 from cpcloud/eval-coverage
CLN: remove dead code in pandas.computation
2 parents 7e2f7bc + 8eea09c commit e2f0b56

File tree

11 files changed

+122
-217
lines changed

11 files changed

+122
-217
lines changed

pandas/computation/align.py

+4-77
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,6 @@ def _zip_axes_from_type(typ, new_axes):
3434
return axes
3535

3636

37-
def _maybe_promote_shape(values, naxes):
38-
# test to see if we have an array else leave since must be a number
39-
if not isinstance(values, np.ndarray):
40-
return values
41-
42-
ndims = values.ndim
43-
if ndims > naxes:
44-
raise AssertionError('cannot have more dims than axes, '
45-
'{0} > {1}'.format(ndims, naxes))
46-
if ndims == naxes:
47-
return values
48-
49-
ndim, nax = range(ndims), range(naxes)
50-
51-
axes_slice = [slice(None)] * naxes
52-
53-
# set difference of numaxes and ndims
54-
slices = list(set(nax) - set(ndim))
55-
56-
if ndims == naxes:
57-
if slices:
58-
raise AssertionError('slices should be empty if ndims == naxes '
59-
'{0}'.format(slices))
60-
else:
61-
if not slices:
62-
raise AssertionError('slices should NOT be empty if ndim != naxes '
63-
'{0}'.format(slices))
64-
65-
for sl in slices:
66-
axes_slice[sl] = np.newaxis
67-
68-
return values[tuple(axes_slice)]
69-
70-
7137
def _any_pandas_objects(terms):
7238
"""Check a sequence of terms for instances of PandasObject."""
7339
return any(isinstance(term.value, pd.core.generic.PandasObject)
@@ -83,12 +49,7 @@ def wrapper(terms):
8349

8450
term_values = (term.value for term in terms)
8551

86-
# only scalars or indexes
87-
if all(isinstance(term.value, pd.Index) or term.isscalar for term in
88-
terms):
89-
return _result_type_many(*term_values), None
90-
91-
# no pandas objects
52+
# we don't have any pandas objects
9253
if not _any_pandas_objects(terms):
9354
return _result_type_many(*term_values), None
9455

@@ -148,44 +109,13 @@ def _align_core(terms):
148109
f = partial(ti.reindex_axis, reindexer, axis=axis,
149110
copy=False)
150111

151-
# need to fill if we have a bool dtype/array
152-
if (isinstance(ti, (np.ndarray, pd.Series))
153-
and ti.dtype == object
154-
and pd.lib.is_bool_array(ti.values)):
155-
r = f(fill_value=True)
156-
else:
157-
r = f()
158-
159-
terms[i].update(r)
112+
terms[i].update(f())
160113

161-
res = _maybe_promote_shape(terms[i].value.T if transpose else
162-
terms[i].value, naxes)
163-
res = res.T if transpose else res
164-
165-
try:
166-
v = res.values
167-
except AttributeError:
168-
v = res
169-
terms[i].update(v)
114+
terms[i].update(terms[i].value.values)
170115

171116
return typ, _zip_axes_from_type(typ, axes)
172117

173118

174-
def _filter_terms(flat):
175-
# numeric literals
176-
literals = frozenset(filter(lambda x: isinstance(x, Constant), flat))
177-
178-
# these are strings which are variable names
179-
names = frozenset(flat) - literals
180-
181-
# literals are not names and names are not literals, so intersection should
182-
# be empty
183-
if literals & names:
184-
raise ValueError('literals cannot be names and names cannot be '
185-
'literals')
186-
return names, literals
187-
188-
189119
def _align(terms):
190120
"""Align a set of terms"""
191121
try:
@@ -231,10 +161,7 @@ def _reconstruct_object(typ, obj, axes, dtype):
231161
except AttributeError:
232162
pass
233163

234-
try:
235-
res_t = np.result_type(obj.dtype, dtype)
236-
except AttributeError:
237-
res_t = dtype
164+
res_t = np.result_type(obj.dtype, dtype)
238165

239166
if (not isinstance(typ, partial) and
240167
issubclass(typ, pd.core.generic.PandasObject)):

pandas/computation/common.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ def _result_type_many(*arrays_and_dtypes):
1616
try:
1717
return np.result_type(*arrays_and_dtypes)
1818
except ValueError:
19-
# length 0 or length > NPY_MAXARGS both throw a ValueError, so check
20-
# which one we're dealing with
21-
if len(arrays_and_dtypes) == 0:
22-
raise ValueError('at least one array or dtype is required')
19+
# we have > NPY_MAXARGS terms in our expression
2320
return reduce(np.result_type, arrays_and_dtypes)
2421

2522

pandas/computation/engines.py

-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ def _evaluate(self):
126126
raise UndefinedVariableError(msg)
127127

128128

129-
130129
class PythonEngine(AbstractEngine):
131130

132131
"""Evaluate an expression in Python space.

pandas/computation/eval.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ def _check_resolvers(resolvers):
6969
for resolver in resolvers:
7070
if not hasattr(resolver, '__getitem__'):
7171
name = type(resolver).__name__
72-
raise AttributeError('Resolver of type {0!r} must implement '
73-
'the __getitem__ method'.format(name))
72+
raise TypeError('Resolver of type %r does not implement '
73+
'the __getitem__ method' % name)
7474

7575

7676
def _check_expression(expr):

pandas/computation/expr.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,6 @@ def visit(self, node, **kwargs):
308308
if isinstance(node, string_types):
309309
clean = self.preparser(node)
310310
node = ast.fix_missing_locations(ast.parse(clean))
311-
elif not isinstance(node, ast.AST):
312-
raise TypeError("Cannot visit objects of type {0!r}"
313-
"".format(node.__class__.__name__))
314311

315312
method = 'visit_' + node.__class__.__name__
316313
visitor = getattr(self, method)
@@ -533,7 +530,7 @@ def visit_Call(self, node, side=None, **kwargs):
533530

534531
args = [self.visit(targ).value for targ in node.args]
535532
if node.starargs is not None:
536-
args = args + self.visit(node.starargs).value
533+
args += self.visit(node.starargs).value
537534

538535
keywords = {}
539536
for key in node.keywords:
@@ -651,10 +648,6 @@ def parse(self):
651648
"""Parse an expression"""
652649
return self._visitor.visit(self.expr)
653650

654-
def align(self):
655-
"""align a set of Terms"""
656-
return self.terms.align(self.env)
657-
658651
@property
659652
def names(self):
660653
"""Get the names in an expression"""

pandas/computation/ops.py

+7-19
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,12 @@ class UndefinedVariableError(NameError):
2929

3030
"""NameError subclass for local variables."""
3131

32-
def __init__(self, *args):
33-
msg = 'name {0!r} is not defined'
34-
subbed = args[0].replace(_LOCAL_TAG, '')
35-
if subbed != args[0]:
36-
subbed = '@' + subbed
32+
def __init__(self, name, is_local):
33+
if is_local:
3734
msg = 'local variable {0!r} is not defined'
38-
super(UndefinedVariableError, self).__init__(msg.format(subbed))
35+
else:
36+
msg = 'name {0!r} is not defined'
37+
super(UndefinedVariableError, self).__init__(msg.format(name))
3938

4039

4140
class Term(StringMixin):
@@ -73,11 +72,6 @@ def _resolve_name(self):
7372
res = self.env.resolve(self.local_name, is_local=self.is_local)
7473
self.update(res)
7574

76-
if res is None:
77-
if not isinstance(key, string_types):
78-
return key
79-
raise UndefinedVariableError(key)
80-
8175
if hasattr(res, 'ndim') and res.ndim > 2:
8276
raise NotImplementedError("N-dimensional objects, where N > 2,"
8377
" are not supported with eval")
@@ -97,10 +91,7 @@ def update(self, value):
9791

9892
# if it's a variable name (otherwise a constant)
9993
if isinstance(key, string_types):
100-
try:
101-
self.env.swapkey(self.local_name, key, new_value=value)
102-
except KeyError:
103-
raise UndefinedVariableError(key)
94+
self.env.swapkey(self.local_name, key, new_value=value)
10495

10596
self.value = value
10697

@@ -156,10 +147,7 @@ def name(self, new_name):
156147

157148
@property
158149
def ndim(self):
159-
try:
160-
return self._value.ndim
161-
except AttributeError:
162-
return 0
150+
return self._value.ndim
163151

164152

165153
class Constant(Term):

pandas/computation/pytables.py

-13
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@ def __init__(self, value, env, side=None, encoding=None):
6767
def _resolve_name(self):
6868
return self._name
6969

70-
@property
71-
def name(self):
72-
return self._value
73-
7470

7571
class BinOp(ops.BinOp):
7672

@@ -233,9 +229,6 @@ def format(self):
233229

234230
def evaluate(self):
235231

236-
if not isinstance(self.lhs, string_types):
237-
return self
238-
239232
if not self.is_valid:
240233
raise ValueError("query term is not valid [%s]" % self)
241234

@@ -307,9 +300,6 @@ def format(self):
307300

308301
def evaluate(self):
309302

310-
if not isinstance(self.lhs, string_types):
311-
return self
312-
313303
if not self.is_valid:
314304
raise ValueError("query term is not valid [%s]" % self)
315305

@@ -390,9 +380,6 @@ def visit_UnaryOp(self, node, **kwargs):
390380
elif isinstance(node.op, ast.UAdd):
391381
raise NotImplementedError('Unary addition not supported')
392382

393-
def visit_USub(self, node, **kwargs):
394-
return self.const_type(-self.visit(node.operand).value, self.env)
395-
396383
def visit_Index(self, node, **kwargs):
397384
return self.visit(node.value).value
398385

pandas/computation/scope.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def resolve(self, key, is_local):
186186
# e.g., df[df > 0]
187187
return self.temps[key]
188188
except KeyError:
189-
raise UndefinedVariableError(key)
189+
raise UndefinedVariableError(key, is_local)
190190

191191
def swapkey(self, old_key, new_key, new_value=None):
192192
"""Replace a variable name, with a potentially new value.
@@ -209,12 +209,8 @@ def swapkey(self, old_key, new_key, new_value=None):
209209

210210
for mapping in maps:
211211
if old_key in mapping:
212-
if new_value is None:
213-
mapping[new_key] = mapping.pop(old_key)
214-
else:
215-
mapping[new_key] = new_value
212+
mapping[new_key] = new_value
216213
return
217-
raise KeyError(old_key)
218214

219215
def _get_vars(self, stack, scopes):
220216
"""Get specifically scoped variables from a list of stack frames.

0 commit comments

Comments
 (0)