@@ -369,7 +369,7 @@ def data(self, index, role=Qt.DisplayRole):
369369 return super ().data (index , role )
370370
371371
372- def freevars (exp , env ):
372+ def freevars (exp : ast . AST , env : List [ str ] ):
373373 """
374374 Return names of all free variables in a parsed (expression) AST.
375375
@@ -402,11 +402,14 @@ def freevars(exp, env):
402402 elif etype == ast .Lambda :
403403 args = exp .args
404404 assert isinstance (args , ast .arguments )
405- argnames = [a .arg for a in args .args ]
406- argnames += [args .vararg .arg ] if args .vararg else []
407- argnames += [a .arg for a in args .kwonlyargs ] if args .kwonlyargs else []
408- argnames += [args .kwarg ] if args .kwarg else []
409- return freevars (exp .body , env + argnames )
405+ arg_names = [a .arg for a in chain (args .posonlyargs , args .args )]
406+ arg_names += [args .vararg .arg ] if args .vararg else []
407+ arg_names += [a .arg for a in args .kwonlyargs ] if args .kwonlyargs else []
408+ arg_names += [args .kwarg .arg ] if args .kwarg else []
409+ vars_ = chain .from_iterable (
410+ freevars (e , env ) for e in chain (args .defaults , args .kw_defaults )
411+ )
412+ return list (vars_ ) + freevars (exp .body , env + arg_names )
410413 elif etype == ast .IfExp :
411414 return (freevars (exp .test , env ) + freevars (exp .body , env ) +
412415 freevars (exp .orelse , env ))
@@ -420,7 +423,7 @@ def freevars(exp, env):
420423 vars_ = []
421424 for gen in exp .generators :
422425 target_names = freevars (gen .target , []) # assigned names
423- vars_iter = freevars (gen .iter , env )
426+ vars_iter = freevars (gen .iter , env + env_ext )
424427 env_ext += target_names
425428 vars_ifs = list (chain (* (freevars (ifexp , env + target_names )
426429 for ifexp in gen .ifs or [])))
@@ -500,7 +503,7 @@ def is_valid_item(self, setting, item, attrs, metas):
500503 for var in metas :
501504 available [sanitized_name (var )] = None
502505
503- if freevars (exp_ast , available ):
506+ if freevars (exp_ast , list ( available ) ):
504507 return False
505508 return True
506509
@@ -944,16 +947,12 @@ def validate_exp(exp):
944947 """
945948 Validate an `ast.AST` expression.
946949
947- Only expressions with no list,set,dict,generator comprehensions
948- are accepted.
949-
950950 Parameters
951951 ----------
952952 exp : ast.AST
953953 A parsed abstract syntax tree
954-
955954 """
956- # pylint: disable=too-many-branches
955+ # pylint: disable=too-many-branches,too-many-return-statements
957956 if not isinstance (exp , ast .AST ):
958957 raise TypeError ("exp is not a 'ast.AST' instance" )
959958
@@ -966,20 +965,28 @@ def validate_exp(exp):
966965 return all (map (validate_exp , [exp .left , exp .right ]))
967966 elif etype == ast .UnaryOp :
968967 return validate_exp (exp .operand )
968+ elif etype == ast .Lambda :
969+ return all (validate_exp (e ) for e in exp .args .defaults ) and \
970+ all (validate_exp (e ) for e in exp .args .kw_defaults ) and \
971+ validate_exp (exp .body )
969972 elif etype == ast .IfExp :
970973 return all (map (validate_exp , [exp .test , exp .body , exp .orelse ]))
971974 elif etype == ast .Dict :
972975 return all (map (validate_exp , chain (exp .keys , exp .values )))
973976 elif etype == ast .Set :
974977 return all (map (validate_exp , exp .elts ))
978+ elif etype in (ast .SetComp , ast .ListComp , ast .GeneratorExp ):
979+ return validate_exp (exp .elt ) and all (map (validate_exp , exp .generators ))
980+ elif etype == ast .DictComp :
981+ return validate_exp (exp .key ) and validate_exp (exp .value ) and \
982+ all (map (validate_exp , exp .generators ))
975983 elif etype == ast .Compare :
976984 return all (map (validate_exp , [exp .left ] + exp .comparators ))
977985 elif etype == ast .Call :
978986 subexp = chain ([exp .func ], exp .args or [],
979987 [k .value for k in exp .keywords or []])
980988 return all (map (validate_exp , subexp ))
981989 elif etype == ast .Starred :
982- assert isinstance (exp .ctx , ast .Load )
983990 return validate_exp (exp .value )
984991 elif etype in [ast .Num , ast .Str , ast .Bytes , ast .Ellipsis , ast .NameConstant ]:
985992 return True
@@ -990,7 +997,6 @@ def validate_exp(exp):
990997 elif etype == ast .Subscript :
991998 return all (map (validate_exp , [exp .value , exp .slice ]))
992999 elif etype in {ast .List , ast .Tuple }:
993- assert isinstance (exp .ctx , ast .Load )
9941000 return all (map (validate_exp , exp .elts ))
9951001 elif etype == ast .Name :
9961002 return True
@@ -1003,6 +1009,9 @@ def validate_exp(exp):
10031009 return validate_exp (exp .value )
10041010 elif etype == ast .keyword :
10051011 return validate_exp (exp .value )
1012+ elif etype == ast .comprehension and not exp .is_async :
1013+ return validate_exp (exp .target ) and validate_exp (exp .iter ) and \
1014+ all (map (validate_exp , exp .ifs ))
10061015 else :
10071016 raise ValueError (exp )
10081017
@@ -1173,9 +1182,9 @@ def make_lambda(expression, args, env=None):
11731182 "bin" , "bool" , "bytearray" , "bytes" , "chr" , "complex" , "dict" ,
11741183 "divmod" , "enumerate" , "filter" , "float" , "format" , "frozenset" ,
11751184 "getattr" , "hasattr" , "hash" , "hex" , "id" , "int" , "iter" , "len" ,
1176- "list" , "map" , "memoryview" , "next" , "object" ,
1185+ "list" , "map" , "max" , " memoryview" , "min " , "next" , "object" ,
11771186 "oct" , "ord" , "pow" , "range" , "repr" , "reversed" , "round" ,
1178- "set" , "slice" , "sorted" , "str" , "tuple" , "type" ,
1187+ "set" , "slice" , "sorted" , "str" , "sum" , " tuple" , "type" ,
11791188 "zip"
11801189]
11811190
@@ -1209,9 +1218,6 @@ def make_lambda(expression, args, env=None):
12091218 "nanargmin" : lambda * args : np .nanargmin (args ),
12101219 "nanvar" : lambda * args : np .nanvar (args ),
12111220 "mean" : lambda * args : np .mean (args ),
1212- "min" : lambda * args : np .min (args ),
1213- "max" : lambda * args : np .max (args ),
1214- "sum" : lambda * args : np .sum (args ),
12151221 "std" : lambda * args : np .std (args ),
12161222 "median" : lambda * args : np .median (args ),
12171223 "cumsum" : lambda * args : np .cumsum (args ),
0 commit comments