Skip to content

Commit a2d468d

Browse files
jbrockmendelyeshsurya
authored andcommitted
TYP: core.computation (pandas-dev#41007)
1 parent 6b1892a commit a2d468d

File tree

6 files changed

+32
-21
lines changed

6 files changed

+32
-21
lines changed

pandas/core/computation/engines.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
align_terms,
1313
reconstruct_object,
1414
)
15+
from pandas.core.computation.expr import Expr
1516
from pandas.core.computation.ops import (
1617
MATHOPS,
1718
REDUCTIONS,
@@ -26,13 +27,13 @@ class NumExprClobberingError(NameError):
2627
pass
2728

2829

29-
def _check_ne_builtin_clash(expr):
30+
def _check_ne_builtin_clash(expr: Expr) -> None:
3031
"""
3132
Attempt to prevent foot-shooting in a helpful way.
3233
3334
Parameters
3435
----------
35-
terms : Term
36+
expr : Expr
3637
Terms can contain
3738
"""
3839
names = expr.names

pandas/core/computation/eval.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
Top level ``eval`` module.
33
"""
4+
from __future__ import annotations
45

56
import tokenize
6-
from typing import Optional
77
import warnings
88

99
from pandas._libs.lib import no_default
@@ -14,13 +14,14 @@
1414
PARSERS,
1515
Expr,
1616
)
17+
from pandas.core.computation.ops import BinOp
1718
from pandas.core.computation.parsing import tokenize_string
1819
from pandas.core.computation.scope import ensure_scope
1920

2021
from pandas.io.formats.printing import pprint_thing
2122

2223

23-
def _check_engine(engine: Optional[str]) -> str:
24+
def _check_engine(engine: str | None) -> str:
2425
"""
2526
Make sure a valid engine is passed.
2627
@@ -161,9 +162,9 @@ def _check_for_locals(expr: str, stack_level: int, parser: str):
161162

162163

163164
def eval(
164-
expr,
165-
parser="pandas",
166-
engine: Optional[str] = None,
165+
expr: str | BinOp, # we leave BinOp out of the docstr bc it isn't for users
166+
parser: str = "pandas",
167+
engine: str | None = None,
167168
truediv=no_default,
168169
local_dict=None,
169170
global_dict=None,
@@ -309,10 +310,12 @@ def eval(
309310
stacklevel=2,
310311
)
311312

313+
exprs: list[str | BinOp]
312314
if isinstance(expr, str):
313315
_check_expression(expr)
314316
exprs = [e.strip() for e in expr.splitlines() if e.strip() != ""]
315317
else:
318+
# ops.BinOp; for internal compat, not intended to be passed by users
316319
exprs = [expr]
317320
multi_line = len(exprs) > 1
318321

pandas/core/computation/pytables.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ class PyTablesExpr(expr.Expr):
546546

547547
_visitor: PyTablesExprVisitor | None
548548
env: PyTablesScope
549+
expr: str
549550

550551
def __init__(
551552
self,
@@ -570,7 +571,7 @@ def __init__(
570571
local_dict = where.env.scope
571572
_where = where.expr
572573

573-
elif isinstance(where, (list, tuple)):
574+
elif is_list_like(where):
574575
where = list(where)
575576
for idx, w in enumerate(where):
576577
if isinstance(w, PyTablesExpr):
@@ -580,6 +581,7 @@ def __init__(
580581
where[idx] = w
581582
_where = " & ".join(f"({w})" for w in com.flatten(where))
582583
else:
584+
# _validate_where ensures we otherwise have a string
583585
_where = where
584586

585587
self.expr = _where

pandas/core/computation/scope.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,13 @@ class Scope:
106106
"""
107107

108108
__slots__ = ["level", "scope", "target", "resolvers", "temps"]
109+
level: int
110+
scope: DeepChainMap
111+
resolvers: DeepChainMap
112+
temps: dict
109113

110114
def __init__(
111-
self, level, global_dict=None, local_dict=None, resolvers=(), target=None
115+
self, level: int, global_dict=None, local_dict=None, resolvers=(), target=None
112116
):
113117
self.level = level + 1
114118

@@ -146,8 +150,7 @@ def __init__(
146150

147151
# assumes that resolvers are going from outermost scope to inner
148152
if isinstance(local_dict, Scope):
149-
# error: Cannot determine type of 'resolvers'
150-
resolvers += tuple(local_dict.resolvers.maps) # type: ignore[has-type]
153+
resolvers += tuple(local_dict.resolvers.maps)
151154
self.resolvers = DeepChainMap(*resolvers)
152155
self.temps = {}
153156

@@ -212,7 +215,7 @@ def resolve(self, key: str, is_local: bool):
212215

213216
raise UndefinedVariableError(key, is_local) from err
214217

215-
def swapkey(self, old_key: str, new_key: str, new_value=None):
218+
def swapkey(self, old_key: str, new_key: str, new_value=None) -> None:
216219
"""
217220
Replace a variable name, with a potentially new value.
218221
@@ -238,7 +241,7 @@ def swapkey(self, old_key: str, new_key: str, new_value=None):
238241
mapping[new_key] = new_value # type: ignore[index]
239242
return
240243

241-
def _get_vars(self, stack, scopes: list[str]):
244+
def _get_vars(self, stack, scopes: list[str]) -> None:
242245
"""
243246
Get specifically scoped variables from a list of stack frames.
244247
@@ -263,7 +266,7 @@ def _get_vars(self, stack, scopes: list[str]):
263266
# scope after the loop
264267
del frame
265268

266-
def _update(self, level: int):
269+
def _update(self, level: int) -> None:
267270
"""
268271
Update the current scope by going back `level` levels.
269272
@@ -313,7 +316,7 @@ def ntemps(self) -> int:
313316
return len(self.temps)
314317

315318
@property
316-
def full_scope(self):
319+
def full_scope(self) -> DeepChainMap:
317320
"""
318321
Return the full scope for use with passing to engines transparently
319322
as a mapping.

pandas/core/reshape/pivot.py

-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ def __internal_pivot_table(
180180
# TODO: why does test_pivot_table_doctest_case fail if
181181
# we don't do this apparently-unnecessary setitem?
182182
agged[v] = agged[v]
183-
pass
184183
else:
185184
agged[v] = maybe_downcast_to_dtype(agged[v], data[v].dtype)
186185

pandas/tests/io/pytables/test_store.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -673,17 +673,20 @@ def test_coordinates(setup_path):
673673
tm.assert_frame_equal(result, expected)
674674

675675
# invalid
676-
msg = "cannot process expression"
677-
with pytest.raises(ValueError, match=msg):
676+
msg = (
677+
"where must be passed as a string, PyTablesExpr, "
678+
"or list-like of PyTablesExpr"
679+
)
680+
with pytest.raises(TypeError, match=msg):
678681
store.select("df", where=np.arange(len(df), dtype="float64"))
679682

680-
with pytest.raises(ValueError, match=msg):
683+
with pytest.raises(TypeError, match=msg):
681684
store.select("df", where=np.arange(len(df) + 1))
682685

683-
with pytest.raises(ValueError, match=msg):
686+
with pytest.raises(TypeError, match=msg):
684687
store.select("df", where=np.arange(len(df)), start=5)
685688

686-
with pytest.raises(ValueError, match=msg):
689+
with pytest.raises(TypeError, match=msg):
687690
store.select("df", where=np.arange(len(df)), start=5, stop=10)
688691

689692
# selection with filter

0 commit comments

Comments
 (0)