17
17
makeCustomDataframe as mkdf )
18
18
19
19
import pandas .util .testing as tm
20
+ import pandas .util ._test_decorators as td
20
21
from pandas .core .computation .check import _NUMEXPR_INSTALLED
21
22
22
23
from pandas .tests .frame .common import TestData
23
24
24
25
25
26
PARSERS = 'python' , 'pandas'
26
- ENGINES = 'python' , 'numexpr'
27
+ ENGINES = 'python' , pytest . param ( 'numexpr' , marks = td . skip_if_no_ne )
27
28
28
29
29
30
@pytest .fixture (params = PARSERS , ids = lambda x : x )
@@ -41,13 +42,6 @@ def skip_if_no_pandas_parser(parser):
41
42
pytest .skip ("cannot evaluate with parser {0!r}" .format (parser ))
42
43
43
44
44
- def skip_if_no_ne (engine = 'numexpr' ):
45
- if engine == 'numexpr' :
46
- if not _NUMEXPR_INSTALLED :
47
- pytest .skip ("cannot query engine numexpr when numexpr not "
48
- "installed" )
49
-
50
-
51
45
class TestCompat (object ):
52
46
53
47
def setup_method (self , method ):
@@ -175,7 +169,6 @@ def test_eval_resolvers_as_list(self):
175
169
class TestDataFrameQueryWithMultiIndex (object ):
176
170
177
171
def test_query_with_named_multiindex (self , parser , engine ):
178
- tm .skip_if_no_ne (engine )
179
172
skip_if_no_pandas_parser (parser )
180
173
a = np .random .choice (['red' , 'green' ], size = 10 )
181
174
b = np .random .choice (['eggs' , 'ham' ], size = 10 )
@@ -225,7 +218,6 @@ def test_query_with_named_multiindex(self, parser, engine):
225
218
assert_frame_equal (res2 , exp )
226
219
227
220
def test_query_with_unnamed_multiindex (self , parser , engine ):
228
- tm .skip_if_no_ne (engine )
229
221
skip_if_no_pandas_parser (parser )
230
222
a = np .random .choice (['red' , 'green' ], size = 10 )
231
223
b = np .random .choice (['eggs' , 'ham' ], size = 10 )
@@ -316,7 +308,6 @@ def test_query_with_unnamed_multiindex(self, parser, engine):
316
308
assert_frame_equal (res2 , exp )
317
309
318
310
def test_query_with_partially_named_multiindex (self , parser , engine ):
319
- tm .skip_if_no_ne (engine )
320
311
skip_if_no_pandas_parser (parser )
321
312
a = np .random .choice (['red' , 'green' ], size = 10 )
322
313
b = np .arange (10 )
@@ -370,27 +361,25 @@ def to_series(mi, level):
370
361
raise AssertionError ("object must be a Series or Index" )
371
362
372
363
def test_raise_on_panel_with_multiindex (self , parser , engine ):
373
- tm .skip_if_no_ne ()
374
364
p = tm .makePanel (7 )
375
365
p .items = tm .makeCustomIndex (len (p .items ), nlevels = 2 )
376
366
with pytest .raises (NotImplementedError ):
377
367
pd .eval ('p + 1' , parser = parser , engine = engine )
378
368
379
369
def test_raise_on_panel4d_with_multiindex (self , parser , engine ):
380
- tm .skip_if_no_ne ()
381
370
p4d = tm .makePanel4D (7 )
382
371
p4d .items = tm .makeCustomIndex (len (p4d .items ), nlevels = 2 )
383
372
with pytest .raises (NotImplementedError ):
384
373
pd .eval ('p4d + 1' , parser = parser , engine = engine )
385
374
386
375
376
+ @td .skip_if_no_ne
387
377
class TestDataFrameQueryNumExprPandas (object ):
388
378
389
379
@classmethod
390
380
def setup_class (cls ):
391
381
cls .engine = 'numexpr'
392
382
cls .parser = 'pandas'
393
- tm .skip_if_no_ne (cls .engine )
394
383
395
384
@classmethod
396
385
def teardown_class (cls ):
@@ -714,14 +703,14 @@ def test_inf(self):
714
703
assert_frame_equal (result , expected )
715
704
716
705
706
+ @td .skip_if_no_ne
717
707
class TestDataFrameQueryNumExprPython (TestDataFrameQueryNumExprPandas ):
718
708
719
709
@classmethod
720
710
def setup_class (cls ):
721
711
super (TestDataFrameQueryNumExprPython , cls ).setup_class ()
722
712
cls .engine = 'numexpr'
723
713
cls .parser = 'python'
724
- tm .skip_if_no_ne (cls .engine )
725
714
cls .frame = TestData ().frame
726
715
727
716
def test_date_query_no_attribute_access (self ):
@@ -859,7 +848,6 @@ def test_query_builtin(self):
859
848
class TestDataFrameQueryStrings (object ):
860
849
861
850
def test_str_query_method (self , parser , engine ):
862
- tm .skip_if_no_ne (engine )
863
851
df = DataFrame (randn (10 , 1 ), columns = ['b' ])
864
852
df ['strings' ] = Series (list ('aabbccddee' ))
865
853
expect = df [df .strings == 'a' ]
@@ -896,7 +884,6 @@ def test_str_query_method(self, parser, engine):
896
884
assert_frame_equal (res , df [~ df .strings .isin (['a' ])])
897
885
898
886
def test_str_list_query_method (self , parser , engine ):
899
- tm .skip_if_no_ne (engine )
900
887
df = DataFrame (randn (10 , 1 ), columns = ['b' ])
901
888
df ['strings' ] = Series (list ('aabbccddee' ))
902
889
expect = df [df .strings .isin (['a' , 'b' ])]
@@ -935,7 +922,6 @@ def test_str_list_query_method(self, parser, engine):
935
922
assert_frame_equal (res , expect )
936
923
937
924
def test_query_with_string_columns (self , parser , engine ):
938
- tm .skip_if_no_ne (engine )
939
925
df = DataFrame ({'a' : list ('aaaabbbbcccc' ),
940
926
'b' : list ('aabbccddeeff' ),
941
927
'c' : np .random .randint (5 , size = 12 ),
@@ -956,7 +942,6 @@ def test_query_with_string_columns(self, parser, engine):
956
942
df .query ('a in b and c < d' , parser = parser , engine = engine )
957
943
958
944
def test_object_array_eq_ne (self , parser , engine ):
959
- tm .skip_if_no_ne (engine )
960
945
df = DataFrame ({'a' : list ('aaaabbbbcccc' ),
961
946
'b' : list ('aabbccddeeff' ),
962
947
'c' : np .random .randint (5 , size = 12 ),
@@ -970,7 +955,6 @@ def test_object_array_eq_ne(self, parser, engine):
970
955
assert_frame_equal (res , exp )
971
956
972
957
def test_query_with_nested_strings (self , parser , engine ):
973
- tm .skip_if_no_ne (engine )
974
958
skip_if_no_pandas_parser (parser )
975
959
raw = """id event timestamp
976
960
1 "page 1 load" 1/1/2014 0:00:01
@@ -995,15 +979,13 @@ def test_query_with_nested_strings(self, parser, engine):
995
979
996
980
def test_query_with_nested_special_character (self , parser , engine ):
997
981
skip_if_no_pandas_parser (parser )
998
- tm .skip_if_no_ne (engine )
999
982
df = DataFrame ({'a' : ['a' , 'b' , 'test & test' ],
1000
983
'b' : [1 , 2 , 3 ]})
1001
984
res = df .query ('a == "test & test"' , parser = parser , engine = engine )
1002
985
expec = df [df .a == 'test & test' ]
1003
986
assert_frame_equal (res , expec )
1004
987
1005
988
def test_query_lex_compare_strings (self , parser , engine ):
1006
- tm .skip_if_no_ne (engine = engine )
1007
989
import operator as opr
1008
990
1009
991
a = Series (np .random .choice (list ('abcde' ), 20 ))
@@ -1018,7 +1000,6 @@ def test_query_lex_compare_strings(self, parser, engine):
1018
1000
assert_frame_equal (res , expected )
1019
1001
1020
1002
def test_query_single_element_booleans (self , parser , engine ):
1021
- tm .skip_if_no_ne (engine )
1022
1003
columns = 'bid' , 'bidsize' , 'ask' , 'asksize'
1023
1004
data = np .random .randint (2 , size = (1 , len (columns ))).astype (bool )
1024
1005
df = DataFrame (data , columns = columns )
@@ -1027,7 +1008,6 @@ def test_query_single_element_booleans(self, parser, engine):
1027
1008
assert_frame_equal (res , expected )
1028
1009
1029
1010
def test_query_string_scalar_variable (self , parser , engine ):
1030
- tm .skip_if_no_ne (engine )
1031
1011
skip_if_no_pandas_parser (parser )
1032
1012
df = pd .DataFrame ({'Symbol' : ['BUD US' , 'BUD US' , 'IBM US' , 'IBM US' ],
1033
1013
'Price' : [109.70 , 109.72 , 183.30 , 183.35 ]})
@@ -1037,63 +1017,29 @@ def test_query_string_scalar_variable(self, parser, engine):
1037
1017
assert_frame_equal (e , r )
1038
1018
1039
1019
1040
- class TestDataFrameEvalNumExprPandas (object ):
1041
-
1042
- @classmethod
1043
- def setup_class (cls ):
1044
- cls .engine = 'numexpr'
1045
- cls .parser = 'pandas'
1046
- tm .skip_if_no_ne ()
1020
+ class TestDataFrameEvalWithFrame (object ):
1047
1021
1048
1022
def setup_method (self , method ):
1049
1023
self .frame = DataFrame (randn (10 , 3 ), columns = list ('abc' ))
1050
1024
1051
1025
def teardown_method (self , method ):
1052
1026
del self .frame
1053
1027
1054
- def test_simple_expr (self ):
1055
- res = self .frame .eval ('a + b' , engine = self . engine , parser = self . parser )
1028
+ def test_simple_expr (self , parser , engine ):
1029
+ res = self .frame .eval ('a + b' , engine = engine , parser = parser )
1056
1030
expect = self .frame .a + self .frame .b
1057
1031
assert_series_equal (res , expect )
1058
1032
1059
- def test_bool_arith_expr (self ):
1060
- res = self .frame .eval ('a[a < 1] + b' , engine = self .engine ,
1061
- parser = self .parser )
1033
+ def test_bool_arith_expr (self , parser , engine ):
1034
+ res = self .frame .eval ('a[a < 1] + b' , engine = engine , parser = parser )
1062
1035
expect = self .frame .a [self .frame .a < 1 ] + self .frame .b
1063
1036
assert_series_equal (res , expect )
1064
1037
1065
- def test_invalid_type_for_operator_raises (self ):
1038
+ def test_invalid_type_for_operator_raises (self , parser , engine ):
1066
1039
df = DataFrame ({'a' : [1 , 2 ], 'b' : ['c' , 'd' ]})
1067
1040
ops = '+' , '-' , '*' , '/'
1068
1041
for op in ops :
1069
1042
with tm .assert_raises_regex (TypeError ,
1070
1043
"unsupported operand type\(s\) "
1071
1044
"for .+: '.+' and '.+'" ):
1072
- df .eval ('a {0} b' .format (op ), engine = self .engine ,
1073
- parser = self .parser )
1074
-
1075
-
1076
- class TestDataFrameEvalNumExprPython (TestDataFrameEvalNumExprPandas ):
1077
-
1078
- @classmethod
1079
- def setup_class (cls ):
1080
- super (TestDataFrameEvalNumExprPython , cls ).setup_class ()
1081
- cls .engine = 'numexpr'
1082
- cls .parser = 'python'
1083
- tm .skip_if_no_ne (cls .engine )
1084
-
1085
-
1086
- class TestDataFrameEvalPythonPandas (TestDataFrameEvalNumExprPandas ):
1087
-
1088
- @classmethod
1089
- def setup_class (cls ):
1090
- super (TestDataFrameEvalPythonPandas , cls ).setup_class ()
1091
- cls .engine = 'python'
1092
- cls .parser = 'pandas'
1093
-
1094
-
1095
- class TestDataFrameEvalPythonPython (TestDataFrameEvalNumExprPython ):
1096
-
1097
- @classmethod
1098
- def setup_class (cls ):
1099
- cls .engine = cls .parser = 'python'
1045
+ df .eval ('a {0} b' .format (op ), engine = engine , parser = parser )
0 commit comments