55of other variables.
66
77"""
8- import sys
98import re
109import copy
1110import functools
2827 QHBoxLayout , QVBoxLayout , QStackedWidget , QStyledItemDelegate ,
2928 QPushButton , QMenu , QListView , QFrame
3029)
31- from AnyQt .QtGui import QIcon , QKeySequence
30+ from AnyQt .QtGui import QKeySequence
3231from AnyQt .QtCore import Qt , pyqtSignal as Signal , pyqtProperty as Property
3332
3433import Orange
@@ -160,7 +159,7 @@ def __init__(self, *args, **kwargs):
160159 self ._modified = False
161160
162161 def setModified (self , modified ):
163- if not type (modified ) is bool :
162+ if not isinstance (modified , bool ) :
164163 raise TypeError
165164
166165 if self ._modified != modified :
@@ -280,14 +279,12 @@ def editorData(self):
280279@functools .lru_cache (20 )
281280def variable_icon (dtype ):
282281 vtype = _VarMap .get (dtype , dtype )
283- try :
284- return gui .attributeIconDict [vtype ]
285- except Exception :
286- return QIcon ()
282+ return gui .attributeIconDict [vtype ]
287283
288284
289285class FeatureItemDelegate (QStyledItemDelegate ):
290- def displayText (self , value , locale ):
286+ @staticmethod
287+ def displayText (value , _ ):
291288 return value .name + " := " + value .expression
292289
293290
@@ -303,18 +300,20 @@ def data(self, index, role=Qt.DisplayRole):
303300class FeatureConstructorHandler (DomainContextHandler ):
304301 """Context handler that filters descriptors"""
305302
306- def is_valid_item (self , setting , descriptor , attrs , metas ):
307- """Check if descriptor can be used with given domain.
303+ def is_valid_item (self , setting , item , attrs , metas ):
304+ """Check if descriptor `item` can be used with given domain.
308305
309306 Return True if descriptor's expression contains only
310307 available variables and descriptors name does not clash with
311308 existing variables.
312309 """
313- if descriptor .name in attrs or descriptor .name in metas :
310+ if item .name in attrs or item .name in metas :
314311 return False
315312
316313 try :
317- exp_ast = ast .parse (descriptor .expression , mode = "eval" )
314+ exp_ast = ast .parse (item .expression , mode = "eval" )
315+ # ast.parse can return arbitrary errors, not only SyntaxError
316+ # pylint: disable=broad-except
318317 except Exception :
319318 return False
320319
@@ -550,9 +549,9 @@ def removeFeature(self, index):
550549 index = selected_row (self .featureview )
551550 if index is not None :
552551 self .setCurrentIndex (index )
553- elif index is None and len ( self .featuremodel ) > 0 :
552+ elif index is None and self .featuremodel . rowCount () :
554553 # Deleting the last item clears selection
555- self .setCurrentIndex (len ( self .featuremodel ) - 1 )
554+ self .setCurrentIndex (self .featuremodel . rowCount ( ) - 1 )
556555
557556 def removeSelectedFeature (self ):
558557 if self .currentIndex >= 0 :
@@ -562,7 +561,8 @@ def duplicateFeature(self):
562561 desc = self .featuremodel [self .currentIndex ]
563562 self .addFeature (copy .deepcopy (desc ))
564563
565- def check_attrs_values (self , attr , data ):
564+ @staticmethod
565+ def check_attrs_values (attr , data ):
566566 for i in range (len (data )):
567567 for var in attr :
568568 if not math .isnan (data [i , var ]) \
@@ -575,6 +575,8 @@ def _validate_descriptors(self, desc):
575575 def validate (source ):
576576 try :
577577 return validate_exp (ast .parse (source , mode = "eval" ))
578+ # ast.parse can return arbitrary errors, not only SyntaxError
579+ # pylint: disable=broad-except
578580 except Exception :
579581 return False
580582
@@ -613,6 +615,8 @@ def apply(self):
613615
614616 try :
615617 data = self .data .transform (new_domain )
618+ # user's expression can contain arbitrary errors
619+ # pylint: disable=broad-except
616620 except Exception as err :
617621 log = logging .getLogger (__name__ )
618622 log .error ("" , exc_info = True )
@@ -661,6 +665,7 @@ def freevars(exp, env):
661665 ast
662666
663667 """
668+ # pylint: disable=too-many-return-statements,too-many-branches
664669 etype = type (exp )
665670 if etype in [ast .Expr , ast .Expression ]:
666671 return freevars (exp .body , env )
@@ -708,25 +713,18 @@ def freevars(exp, env):
708713 elif etype == ast .Compare :
709714 return sum ((freevars (v , env )
710715 for v in [exp .left ] + exp .comparators ), [])
711- elif etype == ast .Call and sys .version_info < (3 , 5 ):
712- return sum ((freevars (e , env )
713- for e in [exp .func ] + (exp .args or []) +
714- ([k .value for k in exp .keywords or []]) +
715- ([exp .starargs ] if exp .starargs else []) +
716- ([exp .kwargs ] if exp .kwargs else [])),
717- [])
718716 elif etype == ast .Call :
719717 return sum (map (lambda e : freevars (e , env ),
720718 chain ([exp .func ],
721719 exp .args or [],
722720 [k .value for k in exp .keywords or []])),
723721 [])
724- elif sys . version_info >= ( 3 , 5 ) and etype == ast .Starred :
722+ elif etype == ast .Starred :
725723 # a 'starred' call parameter (e.g. a and b in `f(x, *a, *b)`
726724 return freevars (exp .value , env )
727725 elif etype in [ast .Num , ast .Str , ast .Ellipsis , ast .Bytes ]:
728726 return []
729- elif sys . version_info >= ( 3 , 4 ) and etype == ast .NameConstant :
727+ elif etype == ast .NameConstant :
730728 return []
731729 elif etype == ast .Attribute :
732730 return freevars (exp .value , env )
@@ -765,6 +763,7 @@ def validate_exp(exp):
765763 A parsed abstract syntax tree
766764
767765 """
766+ # pylint: disable=too-many-branches
768767 if not isinstance (exp , ast .AST ):
769768 raise TypeError ("exp is not a 'ast.AST' instance" )
770769
@@ -788,16 +787,13 @@ def validate_exp(exp):
788787 elif etype == ast .Call :
789788 subexp = chain ([exp .func ], exp .args or [],
790789 [k .value for k in exp .keywords or []])
791- if sys .version_info < (3 , 5 ):
792- extra = [exp .starargs , exp .kwargs ]
793- subexp = chain (subexp , * filter (None , extra ))
794790 return all (map (validate_exp , subexp ))
795- elif sys . version_info >= ( 3 , 5 ) and etype == ast .Starred :
791+ elif etype == ast .Starred :
796792 assert isinstance (exp .ctx , ast .Load )
797793 return validate_exp (exp .value )
798794 elif etype in [ast .Num , ast .Str , ast .Bytes , ast .Ellipsis ]:
799795 return True
800- elif sys . version_info >= ( 3 , 4 ) and etype == ast .NameConstant :
796+ elif etype == ast .NameConstant :
801797 return True
802798 elif etype == ast .Attribute :
803799 return True
@@ -859,7 +855,7 @@ def bind_variable(descriptor, env):
859855 return descriptor , FeatureFunc (descriptor .expression , source_vars , values )
860856
861857
862- def make_lambda (expression , args , env = {} ):
858+ def make_lambda (expression , args , env = None ):
863859 # type: (ast.Expression, List[str], Dict[str, Any]) -> types.FunctionType
864860 """
865861 Create an lambda function from a expression AST.
@@ -870,7 +866,7 @@ def make_lambda(expression, args, env={}):
870866 The body of the lambda.
871867 args : List[str]
872868 A list of positional argument names
873- env : Dict[str, Any]
869+ env : Optional[ Dict[str, Any] ]
874870 Extra environment to capture in the lambda's closure.
875871
876872 Returns
@@ -894,7 +890,7 @@ def make_lambda(expression, args, env={}):
894890 # lambda **{env}** : lambda *{args}*: EXPRESSION
895891 outer = ast .Lambda (
896892 args = ast .arguments (
897- args = [ast .arg (arg = name , annotation = None ) for name in env ],
893+ args = [ast .arg (arg = name , annotation = None ) for name in ( env or {}) ],
898894 varargs = None ,
899895 varargannotation = None ,
900896 kwonlyargs = [],
@@ -909,6 +905,7 @@ def make_lambda(expression, args, env={}):
909905 ast .fix_missing_locations (exp )
910906 GLOBALS = __GLOBALS .copy ()
911907 GLOBALS ["__builtins__" ] = {}
908+ # pylint: disable=eval-used
912909 fouter = eval (compile (exp , "<lambda>" , "eval" ), GLOBALS )
913910 assert isinstance (fouter , types .FunctionType )
914911 finner = fouter (** env )
@@ -980,14 +977,14 @@ class FeatureFunc:
980977 a variable as used in `expression`, and `variable` is the variable
981978 instance used to extract the corresponding column/value from a
982979 Table/Instance.
983- extra_env : Dict[str, Any]
980+ extra_env : Optional[ Dict[str, Any] ]
984981 Extra environment specifying constant values to be made available
985982 in expression. It must not shadow names in `args`
986983 """
987- def __init__ (self , expression , args , extra_env = {} ):
984+ def __init__ (self , expression , args , extra_env = None ):
988985 self .expression = expression
989986 self .args = args
990- self .extra_env = dict (extra_env )
987+ self .extra_env = dict (extra_env or {} )
991988 self .func = make_lambda (ast .parse (expression , mode = "eval" ),
992989 [name for name , _ in args ], self .extra_env )
993990
0 commit comments