From 01d025f49d705de572d710136cc59065cb7ca41f Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 12 Feb 2024 19:47:57 -0500 Subject: [PATCH] Fix evaluations on Python 3.12 List comprehensions no longer get their own scope [1], so adding a level to the (eventual) call to `sys._getframe` goes outside the actual caller. If running in `pytest` (so that there is a scope outside the caller), you end up looking in some unrelated scope. If you are running a script, then `sys._getframe` raises an error that the level is out of bounds. The `Bitwise operations` warning in `test_scalar_unary` appears to always be raised, so remove the condition. [1] https://docs.python.org/3.12/whatsnew/3.12.html#whatsnew312-pep709 --- pandas/io/pytables.py | 7 ++++++- pandas/tests/computation/test_eval.py | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 97b9b905dfd62..db227d8dda0f6 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -39,6 +39,7 @@ ) from pandas._libs.lib import is_string_array from pandas._libs.tslibs import timezones +from pandas.compat import PY312 from pandas.compat._optional import import_optional_dependency from pandas.compat.pickle_compat import patch_pickle from pandas.errors import ( @@ -173,8 +174,12 @@ def _ensure_term(where, scope_level: int): # list level = scope_level + 1 if isinstance(where, (list, tuple)): + # Python 3.12 does not a scope for list comprehensions, but older versions did: + # https://docs.python.org/3.12/whatsnew/3.12.html#whatsnew312-pep709 + if not PY312: + level += 1 where = [ - Term(term, scope_level=level + 1) if maybe_expression(term) else term + Term(term, scope_level=level) if maybe_expression(term) else term for term in where if term is not None ] diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 8e018db05877f..1f839189677e0 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -558,9 +558,7 @@ def test_series_pos(self, lhs, engine, parser): def test_scalar_unary(self, engine, parser): msg = "bad operand type for unary ~: 'float'" - warn = None - if PY312 and not (engine == "numexpr" and parser == "pandas"): - warn = DeprecationWarning + warn = DeprecationWarning if PY312 else None with pytest.raises(TypeError, match=msg): pd.eval("~1.0", engine=engine, parser=parser)