Skip to content

Commit 765eb8d

Browse files
COMPAT: 3.8 compat for tests and DataFrame.query (#28101)
* COMPAT: implement visit_Constant for 3.8 compat * Updated tests for new error messages.
1 parent ea60c19 commit 765eb8d

File tree

6 files changed

+37
-4
lines changed

6 files changed

+37
-4
lines changed

doc/source/whatsnew/v0.25.2.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Sparse
9999
Other
100100
^^^^^
101101

102-
-
102+
- Compatibility with Python 3.8 in :meth:`DataFrame.query` (:issue:`27261`)
103103
-
104104

105105
.. _whatsnew_0.252.contributors:

pandas/compat/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
PY35 = sys.version_info[:2] == (3, 5)
1616
PY36 = sys.version_info >= (3, 6)
1717
PY37 = sys.version_info >= (3, 7)
18+
PY38 = sys.version_info >= (3, 8)
1819
PYPY = platform.python_implementation() == "PyPy"
1920

2021

pandas/core/computation/expr.py

+3
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ def visit_NameConstant(self, node, **kwargs):
582582
def visit_Num(self, node, **kwargs):
583583
return self.const_type(node.n, self.env)
584584

585+
def visit_Constant(self, node, **kwargs):
586+
return self.const_type(node.n, self.env)
587+
585588
def visit_Str(self, node, **kwargs):
586589
name = self.env.add_tmp(node.s)
587590
return self.term_type(name, self.env)

pandas/tests/computation/test_eval.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from pandas.core.dtypes.common import is_bool, is_list_like, is_scalar
1515

1616
import pandas as pd
17-
from pandas import DataFrame, Series, date_range
17+
from pandas import DataFrame, Series, compat, date_range
1818
from pandas.core.computation import pytables
1919
from pandas.core.computation.check import _NUMEXPR_VERSION
2020
from pandas.core.computation.engines import NumExprClobberingError, _engines
@@ -1267,7 +1267,10 @@ def test_assignment_column(self):
12671267
msg = "left hand side of an assignment must be a single name"
12681268
with pytest.raises(SyntaxError, match=msg):
12691269
df.eval("d,c = a + b")
1270-
msg = "can't assign to function call"
1270+
if compat.PY38:
1271+
msg = "cannot assign to function call"
1272+
else:
1273+
msg = "can't assign to function call"
12711274
with pytest.raises(SyntaxError, match=msg):
12721275
df.eval('Timestamp("20131001") = a + b')
12731276

@@ -1967,6 +1970,26 @@ def test_bool_ops_fails_on_scalars(lhs, cmp, rhs, engine, parser):
19671970
pd.eval(ex, engine=engine, parser=parser)
19681971

19691972

1973+
@pytest.mark.parametrize(
1974+
"other",
1975+
[
1976+
"'x'",
1977+
pytest.param(
1978+
"...", marks=pytest.mark.xfail(not compat.PY38, reason="GH-28116")
1979+
),
1980+
],
1981+
)
1982+
def test_equals_various(other):
1983+
df = DataFrame({"A": ["a", "b", "c"]})
1984+
result = df.eval("A == {}".format(other))
1985+
expected = Series([False, False, False], name="A")
1986+
if _USE_NUMEXPR:
1987+
# https://github.com/pandas-dev/pandas/issues/10239
1988+
# lose name with numexpr engine. Remove when that's fixed.
1989+
expected.name = None
1990+
tm.assert_series_equal(result, expected)
1991+
1992+
19701993
def test_inf(engine, parser):
19711994
s = "inf + 1"
19721995
expected = np.inf

pandas/tests/io/parser/test_common.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1898,7 +1898,10 @@ def test_null_byte_char(all_parsers):
18981898
out = parser.read_csv(StringIO(data), names=names)
18991899
tm.assert_frame_equal(out, expected)
19001900
else:
1901-
msg = "NULL byte detected"
1901+
if compat.PY38:
1902+
msg = "line contains NUL"
1903+
else:
1904+
msg = "NULL byte detected"
19021905
with pytest.raises(ParserError, match=msg):
19031906
parser.read_csv(StringIO(data), names=names)
19041907

pandas/tests/scalar/test_nat.py

+3
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ def _get_overlap_public_nat_methods(klass, as_tuple=False):
252252
"day_name",
253253
"dst",
254254
"floor",
255+
"fromisocalendar",
255256
"fromisoformat",
256257
"fromordinal",
257258
"fromtimestamp",
@@ -296,6 +297,8 @@ def test_overlap_public_nat_methods(klass, expected):
296297
# "fromisoformat" was introduced in 3.7
297298
if klass is Timestamp and not compat.PY37:
298299
expected.remove("fromisoformat")
300+
if klass is Timestamp and not compat.PY38:
301+
expected.remove("fromisocalendar")
299302

300303
assert _get_overlap_public_nat_methods(klass) == expected
301304

0 commit comments

Comments
 (0)