20
20
from pandas .computation import pytables
21
21
from pandas .computation .engines import _engines , NumExprClobberingError
22
22
from pandas .computation .expr import PythonExprVisitor , PandasExprVisitor
23
+ from pandas .computation .expressions import _USE_NUMEXPR , _NUMEXPR_INSTALLED
23
24
from pandas .computation .ops import (_binary_ops_dict ,
24
25
_special_case_arith_ops_syms ,
25
26
_arith_ops_syms , _bool_ops_syms ,
38
39
_scalar_skip = 'in' , 'not in'
39
40
40
41
42
+ @pytest .fixture (params = [
43
+ pytest .mark .skipif (engine == 'numexpr' and not _USE_NUMEXPR ,
44
+ reason = 'numexpr enabled->{enabled}, '
45
+ 'installed->{installed}' .format (
46
+ enabled = _USE_NUMEXPR ,
47
+ installed = _NUMEXPR_INSTALLED ))(engine )
48
+ for engine in _engines
49
+ ])
50
+ def engine (request ):
51
+ return request .param
52
+
53
+
54
+ @pytest .fixture (params = expr ._parsers )
55
+ def parser (request ):
56
+ return request .param
57
+
58
+
41
59
def engine_has_neg_frac (engine ):
42
60
return _engines [engine ].has_neg_frac
43
61
@@ -780,14 +798,11 @@ def check_chained_cmp_op(self, lhs, cmp1, mid, cmp2, rhs):
780
798
781
799
782
800
class TestTypeCasting (object ):
783
- @pytest .mark .parametrize ('engine' , _engines )
784
- @pytest .mark .parametrize ('parser' , expr ._parsers )
785
801
@pytest .mark .parametrize ('op' , ['+' , '-' , '*' , '**' , '/' ])
786
802
# maybe someday... numexpr has too many upcasting rules now
787
803
# chain(*(np.sctypes[x] for x in ['uint', 'int', 'float']))
788
804
@pytest .mark .parametrize ('dt' , [np .float32 , np .float64 ])
789
805
def test_binop_typecasting (self , engine , parser , op , dt ):
790
- tm .skip_if_no_ne (engine )
791
806
df = mkdf (5 , 3 , data_gen_f = f , dtype = dt )
792
807
s = 'df {} 3' .format (op )
793
808
res = pd .eval (s , engine = engine , parser = parser )
@@ -820,19 +835,13 @@ class TestAlignment(object):
820
835
index_types = 'i' , 'u' , 'dt'
821
836
lhs_index_types = index_types + ('s' ,) # 'p'
822
837
823
- @pytest .mark .parametrize ('engine' , _engines )
824
- @pytest .mark .parametrize ('parser' , expr ._parsers )
825
838
def test_align_nested_unary_op (self , engine , parser ):
826
- tm .skip_if_no_ne (engine )
827
839
s = 'df * ~2'
828
840
df = mkdf (5 , 3 , data_gen_f = f )
829
841
res = pd .eval (s , engine = engine , parser = parser )
830
842
assert_frame_equal (res , df * ~ 2 )
831
843
832
- @pytest .mark .parametrize ('engine' , _engines )
833
- @pytest .mark .parametrize ('parser' , expr ._parsers )
834
844
def test_basic_frame_alignment (self , engine , parser ):
835
- tm .skip_if_no_ne (engine )
836
845
args = product (self .lhs_index_types , self .index_types ,
837
846
self .index_types )
838
847
with warnings .catch_warnings (record = True ):
@@ -850,10 +859,7 @@ def test_basic_frame_alignment(self, engine, parser):
850
859
res = pd .eval ('df + df2' , engine = engine , parser = parser )
851
860
assert_frame_equal (res , df + df2 )
852
861
853
- @pytest .mark .parametrize ('engine' , _engines )
854
- @pytest .mark .parametrize ('parser' , expr ._parsers )
855
862
def test_frame_comparison (self , engine , parser ):
856
- tm .skip_if_no_ne (engine )
857
863
args = product (self .lhs_index_types , repeat = 2 )
858
864
for r_idx_type , c_idx_type in args :
859
865
df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = r_idx_type ,
@@ -867,10 +873,7 @@ def test_frame_comparison(self, engine, parser):
867
873
assert_frame_equal (res , df < df3 )
868
874
869
875
@slow
870
- @pytest .mark .parametrize ('engine' , _engines )
871
- @pytest .mark .parametrize ('parser' , expr ._parsers )
872
876
def test_medium_complex_frame_alignment (self , engine , parser ):
873
- tm .skip_if_no_ne (engine )
874
877
args = product (self .lhs_index_types , self .index_types ,
875
878
self .index_types , self .index_types )
876
879
@@ -890,11 +893,7 @@ def test_medium_complex_frame_alignment(self, engine, parser):
890
893
engine = engine , parser = parser )
891
894
assert_frame_equal (res , df + df2 + df3 )
892
895
893
- @pytest .mark .parametrize ('engine' , _engines )
894
- @pytest .mark .parametrize ('parser' , expr ._parsers )
895
896
def test_basic_frame_series_alignment (self , engine , parser ):
896
- tm .skip_if_no_ne (engine )
897
-
898
897
def testit (r_idx_type , c_idx_type , index_name ):
899
898
df = mkdf (10 , 10 , data_gen_f = f , r_idx_type = r_idx_type ,
900
899
c_idx_type = c_idx_type )
@@ -920,11 +919,7 @@ def testit(r_idx_type, c_idx_type, index_name):
920
919
for r_idx_type , c_idx_type , index_name in args :
921
920
testit (r_idx_type , c_idx_type , index_name )
922
921
923
- @pytest .mark .parametrize ('engine' , _engines )
924
- @pytest .mark .parametrize ('parser' , expr ._parsers )
925
922
def test_basic_series_frame_alignment (self , engine , parser ):
926
- tm .skip_if_no_ne (engine )
927
-
928
923
def testit (r_idx_type , c_idx_type , index_name ):
929
924
df = mkdf (10 , 7 , data_gen_f = f , r_idx_type = r_idx_type ,
930
925
c_idx_type = c_idx_type )
@@ -954,10 +949,7 @@ def testit(r_idx_type, c_idx_type, index_name):
954
949
for r_idx_type , c_idx_type , index_name in args :
955
950
testit (r_idx_type , c_idx_type , index_name )
956
951
957
- @pytest .mark .parametrize ('engine' , _engines )
958
- @pytest .mark .parametrize ('parser' , expr ._parsers )
959
952
def test_series_frame_commutativity (self , engine , parser ):
960
- tm .skip_if_no_ne (engine )
961
953
args = product (self .lhs_index_types , self .index_types , ('+' , '*' ),
962
954
('index' , 'columns' ))
963
955
@@ -985,11 +977,7 @@ def test_series_frame_commutativity(self, engine, parser):
985
977
assert_frame_equal (a , b )
986
978
987
979
@slow
988
- @pytest .mark .parametrize ('engine' , _engines )
989
- @pytest .mark .parametrize ('parser' , expr ._parsers )
990
980
def test_complex_series_frame_alignment (self , engine , parser ):
991
- tm .skip_if_no_ne (engine )
992
-
993
981
import random
994
982
args = product (self .lhs_index_types , self .index_types ,
995
983
self .index_types , self .index_types )
@@ -1033,10 +1021,7 @@ def test_complex_series_frame_alignment(self, engine, parser):
1033
1021
tm .assert_equal (res .shape , expected .shape )
1034
1022
assert_frame_equal (res , expected )
1035
1023
1036
- @pytest .mark .parametrize ('engine' , _engines )
1037
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1038
1024
def test_performance_warning_for_poor_alignment (self , engine , parser ):
1039
- tm .skip_if_no_ne (engine )
1040
1025
df = DataFrame (randn (1000 , 10 ))
1041
1026
s = Series (randn (10000 ))
1042
1027
if engine == 'numexpr' :
@@ -1737,29 +1722,20 @@ def setUpClass(cls):
1737
1722
1738
1723
class TestScope (object ):
1739
1724
1740
- @pytest .mark .parametrize ('engine' , _engines )
1741
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1742
1725
def test_global_scope (self , engine , parser ):
1743
- tm .skip_if_no_ne (engine )
1744
1726
e = '_var_s * 2'
1745
1727
tm .assert_numpy_array_equal (_var_s * 2 , pd .eval (e , engine = engine ,
1746
1728
parser = parser ))
1747
1729
1748
- @pytest .mark .parametrize ('engine' , _engines )
1749
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1750
1730
def test_no_new_locals (self , engine , parser ):
1751
- tm .skip_if_no_ne (engine )
1752
1731
x = 1
1753
1732
lcls = locals ().copy ()
1754
1733
pd .eval ('x + 1' , local_dict = lcls , engine = engine , parser = parser )
1755
1734
lcls2 = locals ().copy ()
1756
1735
lcls2 .pop ('lcls' )
1757
1736
tm .assert_equal (lcls , lcls2 )
1758
1737
1759
- @pytest .mark .parametrize ('engine' , _engines )
1760
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1761
1738
def test_no_new_globals (self , engine , parser ):
1762
- tm .skip_if_no_ne (engine )
1763
1739
x = 1
1764
1740
gbls = globals ().copy ()
1765
1741
pd .eval ('x + 1' , engine = engine , parser = parser )
@@ -1798,29 +1774,19 @@ def test_disallowed_nodes(engine, parser):
1798
1774
getattr (inst , ops )()
1799
1775
1800
1776
1801
- @pytest .mark .parametrize ('engine' , _engines )
1802
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1803
1777
def test_syntax_error_exprs (engine , parser ):
1804
- tm .skip_if_no_ne (engine )
1805
1778
e = 's +'
1806
1779
with pytest .raises (SyntaxError ):
1807
1780
pd .eval (e , engine = engine , parser = parser )
1808
1781
1809
1782
1810
- @pytest .mark .parametrize ('engine' , _engines )
1811
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1812
1783
def test_name_error_exprs (engine , parser ):
1813
- tm .skip_if_no_ne (engine )
1814
1784
e = 's + t'
1815
1785
with tm .assertRaises (NameError ):
1816
1786
pd .eval (e , engine = engine , parser = parser )
1817
1787
1818
1788
1819
- @pytest .mark .parametrize ('engine' , _engines )
1820
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1821
1789
def test_invalid_local_variable_reference (engine , parser ):
1822
- tm .skip_if_no_ne (engine )
1823
-
1824
1790
a , b = 1 , 2
1825
1791
exprs = 'a + @b' , '@a + b' , '@a + @b'
1826
1792
for expr in exprs :
@@ -1832,10 +1798,7 @@ def test_invalid_local_variable_reference(engine, parser):
1832
1798
pd .eval (exprs , engine = engine , parser = parser )
1833
1799
1834
1800
1835
- @pytest .mark .parametrize ('engine' , _engines )
1836
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1837
1801
def test_numexpr_builtin_raises (engine , parser ):
1838
- tm .skip_if_no_ne (engine )
1839
1802
sin , dotted_line = 1 , 2
1840
1803
if engine == 'numexpr' :
1841
1804
with tm .assertRaisesRegexp (NumExprClobberingError ,
@@ -1846,41 +1809,29 @@ def test_numexpr_builtin_raises(engine, parser):
1846
1809
tm .assert_equal (res , sin + dotted_line )
1847
1810
1848
1811
1849
- @pytest .mark .parametrize ('engine' , _engines )
1850
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1851
1812
def test_bad_resolver_raises (engine , parser ):
1852
- tm .skip_if_no_ne (engine )
1853
1813
cannot_resolve = 42 , 3.0
1854
1814
with tm .assertRaisesRegexp (TypeError , 'Resolver of type .+' ):
1855
1815
pd .eval ('1 + 2' , resolvers = cannot_resolve , engine = engine ,
1856
1816
parser = parser )
1857
1817
1858
1818
1859
- @pytest .mark .parametrize ('engine' , _engines )
1860
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1861
1819
def test_empty_string_raises (engine , parser ):
1862
1820
# GH 13139
1863
- tm .skip_if_no_ne (engine )
1864
1821
with tm .assertRaisesRegexp (ValueError , 'expr cannot be an empty string' ):
1865
1822
pd .eval ('' , engine = engine , parser = parser )
1866
1823
1867
1824
1868
- @pytest .mark .parametrize ('engine' , _engines )
1869
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1870
1825
def test_more_than_one_expression_raises (engine , parser ):
1871
- tm .skip_if_no_ne (engine )
1872
1826
with tm .assertRaisesRegexp (SyntaxError ,
1873
1827
'only a single expression is allowed' ):
1874
1828
pd .eval ('1 + 1; 2 + 2' , engine = engine , parser = parser )
1875
1829
1876
1830
1877
- @pytest .mark .parametrize ('engine' , _engines )
1878
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1879
1831
@pytest .mark .parametrize ('cmp' , ('and' , 'or' ))
1880
1832
@pytest .mark .parametrize ('lhs' , (int , float ))
1881
1833
@pytest .mark .parametrize ('rhs' , (int , float ))
1882
1834
def test_bool_ops_fails_on_scalars (lhs , cmp , rhs , engine , parser ):
1883
- tm .skip_if_no_ne (engine )
1884
1835
gen = {int : lambda : np .random .randint (10 ), float : np .random .randn }
1885
1836
1886
1837
mid = gen [lhs ]()
@@ -1895,20 +1846,14 @@ def test_bool_ops_fails_on_scalars(lhs, cmp, rhs, engine, parser):
1895
1846
pd .eval (ex , engine = engine , parser = parser )
1896
1847
1897
1848
1898
- @pytest .mark .parametrize ('engine' , _engines )
1899
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1900
1849
def test_inf (engine , parser ):
1901
- tm .skip_if_no_ne (engine )
1902
1850
s = 'inf + 1'
1903
1851
expected = np .inf
1904
1852
result = pd .eval (s , engine = engine , parser = parser )
1905
1853
tm .assert_equal (result , expected )
1906
1854
1907
1855
1908
- @pytest .mark .parametrize ('engine' , _engines )
1909
- @pytest .mark .parametrize ('parser' , expr ._parsers )
1910
1856
def test_negate_lt_eq_le (engine , parser ):
1911
- tm .skip_if_no_ne (engine )
1912
1857
df = pd .DataFrame ([[0 , 10 ], [1 , 20 ]], columns = ['cat' , 'count' ])
1913
1858
expected = df [~ (df .cat > 0 )]
1914
1859
0 commit comments