11import ast
22import importlib
33import os
4- import re
54from types import ModuleType
65from typing import Any , Dict , Iterator , Set
76
87LINE_IDENTIFIER = "_"
98_TYPE_ERROR_MSG = "The provided expression must be an str (editing) or a bool (filtering), but got {}."
109
1110
12- def iter_identifiers (expr : str ) -> Iterator [str ]:
13- for node in iter_asts (ast .parse (expr , mode = "eval" ).body ):
11+ def iter_identifiers (expression : str ) -> Iterator [str ]:
12+ for node in iter_asts (ast .parse (expression , mode = "eval" ).body ):
1413 if isinstance (node , ast .Name ):
1514 yield node .id
1615
@@ -27,19 +26,13 @@ def iter_asts(node: ast.AST) -> Iterator[ast.AST]:
2726
2827def auto_import_eval (expression : str , globals : Dict [str , Any ]) -> Any :
2928 globals = globals .copy ()
30- encountered_name_errors : Set [str ] = set ()
31- while True :
32- try :
33- return eval (expression , globals )
34- except NameError as name_error :
35- if str (name_error ) in encountered_name_errors :
36- raise
37- encountered_name_errors .add (str (name_error ))
38- match = re .match (r"name '([A-Za-z]+)'.*" , str (name_error ))
39- if match :
40- module = match .group (1 )
41- globals [module ] = importlib .import_module (module )
29+ for identifier in iter_identifiers (expression ):
30+ if identifier != LINE_IDENTIFIER :
31+ try :
32+ globals [identifier ] = importlib .import_module (identifier )
33+ except ModuleNotFoundError :
4234 continue
35+ return eval (expression , globals = globals )
4336
4437
4538def edit (lines : Iterator [str ], expression ) -> Iterator [str ]:
0 commit comments