Skip to content

Commit eb6071f

Browse files
committed
MAINT: Enforce string type for where parameter
Deprecated in 0.11.0. xref gh-12027.
1 parent 9d3554c commit eb6071f

File tree

2 files changed

+23
-113
lines changed

2 files changed

+23
-113
lines changed

pandas/computation/pytables.py

+23-60
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
""" manage PyTables query interface via Expressions """
22

33
import ast
4-
import warnings
54
from functools import partial
6-
from datetime import datetime, timedelta
75
import numpy as np
86
import pandas as pd
97

@@ -452,6 +450,26 @@ def _rewrite_membership_op(self, node, left, right):
452450
return self.visit(node.op), node.op, left, right
453451

454452

453+
def _validate_where(w):
454+
"""
455+
Validate that the where statement is of the right type.
456+
457+
The type may either be String, Expr, or list-like of Exprs.
458+
459+
Parameters
460+
----------
461+
w : String term expression, Expr, or list-like of Exprs.
462+
463+
Raises
464+
------
465+
TypeError : An invalid data type was passed in for w (e.g. dict).
466+
"""
467+
468+
if not (isinstance(w, (Expr, string_types)) or is_list_like(w)):
469+
raise TypeError("where must be passed as a string, Expr, "
470+
"or list-like of Exprs")
471+
472+
455473
class Expr(expr.Expr):
456474

457475
""" hold a pytables like expression, comprised of possibly multiple 'terms'
@@ -481,11 +499,9 @@ class Expr(expr.Expr):
481499
"major_axis>=20130101"
482500
"""
483501

484-
def __init__(self, where, op=None, value=None, queryables=None,
485-
encoding=None, scope_level=0):
502+
def __init__(self, where, queryables=None, encoding=None, scope_level=0):
486503

487-
# try to be back compat
488-
where = self.parse_back_compat(where, op, value)
504+
_validate_where(where)
489505

490506
self.encoding = encoding
491507
self.condition = None
@@ -505,7 +521,7 @@ def __init__(self, where, op=None, value=None, queryables=None,
505521
if isinstance(w, Expr):
506522
local_dict = w.env.scope
507523
else:
508-
w = self.parse_back_compat(w)
524+
_validate_where(w)
509525
where[idx] = w
510526
where = ' & ' .join(["(%s)" % w for w in where]) # noqa
511527

@@ -519,59 +535,6 @@ def __init__(self, where, op=None, value=None, queryables=None,
519535
encoding=encoding)
520536
self.terms = self.parse()
521537

522-
def parse_back_compat(self, w, op=None, value=None):
523-
""" allow backward compatibility for passed arguments """
524-
525-
if isinstance(w, dict):
526-
w, op, value = w.get('field'), w.get('op'), w.get('value')
527-
if not isinstance(w, string_types):
528-
raise TypeError(
529-
"where must be passed as a string if op/value are passed")
530-
warnings.warn("passing a dict to Expr is deprecated, "
531-
"pass the where as a single string",
532-
FutureWarning, stacklevel=10)
533-
if isinstance(w, tuple):
534-
if len(w) == 2:
535-
w, value = w
536-
op = '=='
537-
elif len(w) == 3:
538-
w, op, value = w
539-
warnings.warn("passing a tuple into Expr is deprecated, "
540-
"pass the where as a single string",
541-
FutureWarning, stacklevel=10)
542-
543-
if op is not None:
544-
if not isinstance(w, string_types):
545-
raise TypeError(
546-
"where must be passed as a string if op/value are passed")
547-
548-
if isinstance(op, Expr):
549-
raise TypeError("invalid op passed, must be a string")
550-
w = "{0}{1}".format(w, op)
551-
if value is not None:
552-
if isinstance(value, Expr):
553-
raise TypeError("invalid value passed, must be a string")
554-
555-
# stringify with quotes these values
556-
def convert(v):
557-
if isinstance(v, (datetime, np.datetime64,
558-
timedelta, np.timedelta64)):
559-
return "'{0}'".format(v)
560-
return v
561-
562-
if isinstance(value, (list, tuple)):
563-
value = [convert(v) for v in value]
564-
else:
565-
value = convert(value)
566-
567-
w = "{0}{1}".format(w, value)
568-
569-
warnings.warn("passing multiple values to Expr is deprecated, "
570-
"pass the where as a single string",
571-
FutureWarning, stacklevel=10)
572-
573-
return w
574-
575538
def __unicode__(self):
576539
if self.terms is not None:
577540
return pprint_thing(self.terms)

pandas/tests/io/test_pytables.py

-53
Original file line numberDiff line numberDiff line change
@@ -2585,59 +2585,6 @@ def test_term_compat(self):
25852585
expected = wp.loc[:, :, ['A', 'B']]
25862586
assert_panel_equal(result, expected)
25872587

2588-
def test_backwards_compat_without_term_object(self):
2589-
with ensure_clean_store(self.path) as store:
2590-
2591-
wp = Panel(np.random.randn(2, 5, 4), items=['Item1', 'Item2'],
2592-
major_axis=date_range('1/1/2000', periods=5),
2593-
minor_axis=['A', 'B', 'C', 'D'])
2594-
store.append('wp', wp)
2595-
with catch_warnings(record=True):
2596-
result = store.select('wp', [('major_axis>20000102'),
2597-
('minor_axis', '=', ['A', 'B'])])
2598-
expected = wp.loc[:,
2599-
wp.major_axis > Timestamp('20000102'),
2600-
['A', 'B']]
2601-
assert_panel_equal(result, expected)
2602-
2603-
store.remove('wp', ('major_axis>20000103'))
2604-
result = store.select('wp')
2605-
expected = wp.loc[:, wp.major_axis <= Timestamp('20000103'), :]
2606-
assert_panel_equal(result, expected)
2607-
2608-
with ensure_clean_store(self.path) as store:
2609-
2610-
wp = Panel(np.random.randn(2, 5, 4), items=['Item1', 'Item2'],
2611-
major_axis=date_range('1/1/2000', periods=5),
2612-
minor_axis=['A', 'B', 'C', 'D'])
2613-
store.append('wp', wp)
2614-
2615-
# stringified datetimes
2616-
with catch_warnings(record=True):
2617-
result = store.select('wp',
2618-
[('major_axis',
2619-
'>',
2620-
datetime.datetime(2000, 1, 2))])
2621-
expected = wp.loc[:, wp.major_axis > Timestamp('20000102')]
2622-
assert_panel_equal(result, expected)
2623-
with catch_warnings(record=True):
2624-
result = store.select('wp',
2625-
[('major_axis',
2626-
'>',
2627-
datetime.datetime(2000, 1, 2, 0, 0))])
2628-
expected = wp.loc[:, wp.major_axis > Timestamp('20000102')]
2629-
assert_panel_equal(result, expected)
2630-
with catch_warnings(record=True):
2631-
result = store.select('wp',
2632-
[('major_axis',
2633-
'=',
2634-
[datetime.datetime(2000, 1, 2, 0, 0),
2635-
datetime.datetime(2000, 1, 3, 0, 0)])]
2636-
)
2637-
expected = wp.loc[:, [Timestamp('20000102'),
2638-
Timestamp('20000103')]]
2639-
assert_panel_equal(result, expected)
2640-
26412588
def test_same_name_scoping(self):
26422589

26432590
with ensure_clean_store(self.path) as store:

0 commit comments

Comments
 (0)