1- """:func:`~pandas.eval` parsers
1+ """
2+ :func:`~pandas.eval` parsers.
23"""
34
45import ast
56from functools import partial , reduce
67from keyword import iskeyword
78import tokenize
8- from typing import Optional , Type
9+ from typing import Callable , Optional , Set , Tuple , Type , TypeVar
910
1011import numpy as np
1112
3435import pandas .io .formats .printing as printing
3536
3637
37- def _rewrite_assign (tok ):
38- """Rewrite the assignment operator for PyTables expressions that use ``=``
38+ def _rewrite_assign (tok : Tuple [int , str ]) -> Tuple [int , str ]:
39+ """
40+ Rewrite the assignment operator for PyTables expressions that use ``=``
3941 as a substitute for ``==``.
4042
4143 Parameters
@@ -45,15 +47,16 @@ def _rewrite_assign(tok):
4547
4648 Returns
4749 -------
48- t : tuple of int, str
50+ tuple of int, str
4951 Either the input or token or the replacement values
5052 """
5153 toknum , tokval = tok
5254 return toknum , "==" if tokval == "=" else tokval
5355
5456
55- def _replace_booleans (tok ):
56- """Replace ``&`` with ``and`` and ``|`` with ``or`` so that bitwise
57+ def _replace_booleans (tok : Tuple [int , str ]) -> Tuple [int , str ]:
58+ """
59+ Replace ``&`` with ``and`` and ``|`` with ``or`` so that bitwise
5760 precedence is changed to boolean precedence.
5861
5962 Parameters
@@ -63,7 +66,7 @@ def _replace_booleans(tok):
6366
6467 Returns
6568 -------
66- t : tuple of int, str
69+ tuple of int, str
6770 Either the input or token or the replacement values
6871 """
6972 toknum , tokval = tok
@@ -76,8 +79,9 @@ def _replace_booleans(tok):
7679 return toknum , tokval
7780
7881
79- def _replace_locals (tok ):
80- """Replace local variables with a syntactically valid name.
82+ def _replace_locals (tok : Tuple [int , str ]) -> Tuple [int , str ]:
83+ """
84+ Replace local variables with a syntactically valid name.
8185
8286 Parameters
8387 ----------
@@ -86,7 +90,7 @@ def _replace_locals(tok):
8690
8791 Returns
8892 -------
89- t : tuple of int, str
93+ tuple of int, str
9094 Either the input or token or the replacement values
9195
9296 Notes
@@ -102,12 +106,16 @@ def _replace_locals(tok):
102106
103107
104108def _compose2 (f , g ):
105- """Compose 2 callables"""
109+ """
110+ Compose 2 callables.
111+ """
106112 return lambda * args , ** kwargs : f (g (* args , ** kwargs ))
107113
108114
109115def _compose (* funcs ):
110- """Compose 2 or more callables"""
116+ """
117+ Compose 2 or more callables.
118+ """
111119 assert len (funcs ) > 1 , "At least 2 callables must be passed to compose"
112120 return reduce (_compose2 , funcs )
113121
@@ -117,8 +125,9 @@ def _preparse(
117125 f = _compose (
118126 _replace_locals , _replace_booleans , _rewrite_assign , clean_backtick_quoted_toks
119127 ),
120- ):
121- """Compose a collection of tokenization functions
128+ ) -> str :
129+ """
130+ Compose a collection of tokenization functions.
122131
123132 Parameters
124133 ----------
@@ -132,7 +141,7 @@ def _preparse(
132141
133142 Returns
134143 -------
135- s : str
144+ str
136145 Valid Python source code
137146
138147 Notes
@@ -146,7 +155,9 @@ def _preparse(
146155
147156
148157def _is_type (t ):
149- """Factory for a type checking function of type ``t`` or tuple of types."""
158+ """
159+ Factory for a type checking function of type ``t`` or tuple of types.
160+ """
150161 return lambda x : isinstance (x .value , t )
151162
152163
@@ -164,7 +175,9 @@ def _is_type(t):
164175
165176
166177def _filter_nodes (superclass , all_nodes = _all_nodes ):
167- """Filter out AST nodes that are subclasses of ``superclass``."""
178+ """
179+ Filter out AST nodes that are subclasses of ``superclass``.
180+ """
168181 node_names = (node .__name__ for node in all_nodes if issubclass (node , superclass ))
169182 return frozenset (node_names )
170183
@@ -227,30 +240,35 @@ def _filter_nodes(superclass, all_nodes=_all_nodes):
227240assert not intersection , _msg
228241
229242
230- def _node_not_implemented (node_name , cls ):
231- """Return a function that raises a NotImplementedError with a passed node
232- name.
243+ # TODO: Python 3.6.2: replace Callable[..., None] with Callable[..., NoReturn]
244+ def _node_not_implemented (node_name : str ) -> Callable [..., None ]:
245+ """
246+ Return a function that raises a NotImplementedError with a passed node name.
233247 """
234248
235249 def f (self , * args , ** kwargs ):
236- raise NotImplementedError (f"{ repr ( node_name ) } nodes are not implemented" )
250+ raise NotImplementedError (f"' { node_name } ' nodes are not implemented" )
237251
238252 return f
239253
240254
241- def disallow (nodes ):
242- """Decorator to disallow certain nodes from parsing. Raises a
255+ _T = TypeVar ("_T" , bound = "BaseExprVisitor" )
256+
257+
258+ def disallow (nodes : Set [str ]) -> Callable [[Type [_T ]], Type [_T ]]:
259+ """
260+ Decorator to disallow certain nodes from parsing. Raises a
243261 NotImplementedError instead.
244262
245263 Returns
246264 -------
247- disallowed : callable
265+ callable
248266 """
249267
250- def disallowed (cls ) :
268+ def disallowed (cls : Type [ _T ]) -> Type [ _T ] :
251269 cls .unsupported_nodes = ()
252270 for node in nodes :
253- new_method = _node_not_implemented (node , cls )
271+ new_method = _node_not_implemented (node )
254272 name = f"visit_{ node } "
255273 cls .unsupported_nodes += (name ,)
256274 setattr (cls , name , new_method )
@@ -260,20 +278,21 @@ def disallowed(cls):
260278
261279
262280def _op_maker (op_class , op_symbol ):
263- """Return a function to create an op class with its symbol already passed.
281+ """
282+ Return a function to create an op class with its symbol already passed.
264283
265284 Returns
266285 -------
267- f : callable
286+ callable
268287 """
269288
270289 def f (self , node , * args , ** kwargs ):
271- """Return a partial function with an Op subclass with an operator
272- already passed.
290+ """
291+ Return a partial function with an Op subclass with an operator already passed.
273292
274293 Returns
275294 -------
276- f : callable
295+ callable
277296 """
278297 return partial (op_class , op_symbol , * args , ** kwargs )
279298
@@ -284,7 +303,9 @@ def f(self, node, *args, **kwargs):
284303
285304
286305def add_ops (op_classes ):
287- """Decorator to add default implementation of ops."""
306+ """
307+ Decorator to add default implementation of ops.
308+ """
288309
289310 def f (cls ):
290311 for op_attr_name , op_class in op_classes .items ():
@@ -353,6 +374,8 @@ class BaseExprVisitor(ast.NodeVisitor):
353374 ast .NotIn : ast .NotIn ,
354375 }
355376
377+ unsupported_nodes : Tuple [str , ...]
378+
356379 def __init__ (self , env , engine , parser , preparser = _preparse ):
357380 self .env = env
358381 self .engine = engine
@@ -647,7 +670,7 @@ def visit_Call(self, node, side=None, **kwargs):
647670 f'Function "{ res .name } " does not support keyword arguments'
648671 )
649672
650- return res (* new_args , ** kwargs )
673+ return res (* new_args )
651674
652675 else :
653676
@@ -777,12 +800,16 @@ def __len__(self) -> int:
777800 return len (self .expr )
778801
779802 def parse (self ):
780- """Parse an expression"""
803+ """
804+ Parse an expression.
805+ """
781806 return self ._visitor .visit (self .expr )
782807
783808 @property
784809 def names (self ):
785- """Get the names in an expression"""
810+ """
811+ Get the names in an expression.
812+ """
786813 if is_term (self .terms ):
787814 return frozenset ([self .terms .name ])
788815 return frozenset (term .name for term in com .flatten (self .terms ))
0 commit comments