From: Neal N. <nno...@us...> - 2002-03-30 18:06:00
|
Update of /cvsroot/pychecker/pychecker/pychecker In directory usw-pr-cvs1:/tmp/cvs-serv12278/pychecker Modified Files: CodeChecks.py OP.py msgs.py Log Message: Impl warnings for catching string exceptions (and non-Exception classes) Found problems with handling STORE_SUBSCR, fix that. Didn't handle BUILD_CLASS, also needed to handle that. Index: CodeChecks.py =================================================================== RCS file: /cvsroot/pychecker/pychecker/pychecker/CodeChecks.py,v retrieving revision 1.112 retrieving revision 1.113 diff -C2 -d -r1.112 -r1.113 *** CodeChecks.py 29 Mar 2002 15:18:04 -0000 1.112 --- CodeChecks.py 30 Mar 2002 18:05:55 -0000 1.113 *************** *** 420,424 **** compareValues.append(None) stack[-si:] = [ Stack.makeComparison(compareValues, operand) ] ! def _handleImport(code, operand, module, main, fromName) : --- 420,424 ---- compareValues.append(None) stack[-si:] = [ Stack.makeComparison(compareValues, operand) ] ! return compareValues def _handleImport(code, operand, module, main, fromName) : *************** *** 1076,1081 **** _checkAttribute(code.stack[-1], operand, codeSource, code) def _COMPARE_OP(oparg, operand, codeSource, code) : ! _handleComparison(code.stack, operand) def _IMPORT_NAME(oparg, operand, codeSource, code) : --- 1076,1129 ---- _checkAttribute(code.stack[-1], operand, codeSource, code) + def _getExceptionInfo(codeSource, item): + # FIXME: probably ought to try to handle raise module.Error + if item.type is types.StringType and item.const == 1: + return item.data, 1 + + e = None + if item.type is Stack.TYPE_GLOBAL: + try: + e = eval(item.data) + except NameError: + pass + + if not e: + c = codeSource.module.classes.get(item.data) + if c is not None: + e = c.classObject + else: + v = codeSource.module.variables.get(item.data) + if v is not None: + return v, 1 + return e, 0 + + _UNCHECKABLE_CATCH_TYPES = (Stack.TYPE_UNKNOWN, Stack.TYPE_ATTRIBUTE) + def _checkCatchException(codeSource, code, item): + if not cfg().badExceptions: + return + + if item.data is None or item.type in _UNCHECKABLE_CATCH_TYPES: + return + + e, is_str = _getExceptionInfo(codeSource, item) + if is_str: + code.addWarning(msgs.CATCH_STR_EXCEPTION % item.data) + elif e is not None and not _isexception(e): + code.addWarning(msgs.CATCH_BAD_EXCEPTION % item.data) + + def _handleExceptionChecks(codeSource, code, checks): + for item in checks: + if item is not None: + if item.type is not types.TupleType: + _checkCatchException(codeSource, code, item) + else: + for ti in item.data: + if isinstance(ti, Stack.Item): + _checkCatchException(codeSource, code, ti) + def _COMPARE_OP(oparg, operand, codeSource, code) : ! compareValues = _handleComparison(code.stack, operand) ! if operand is OP.EXCEPT_COMPARE: ! _handleExceptionChecks(codeSource, code, compareValues) def _IMPORT_NAME(oparg, operand, codeSource, code) : *************** *** 1102,1106 **** code.pushStack(code.stack[-1]) ! def _pop2(oparg, operand, codeSource, code) : if len(code.stack) >= 2 : loadValue = code.stack[-2] --- 1150,1154 ---- code.pushStack(code.stack[-1]) ! def _popn(code, n) : if len(code.stack) >= 2 : loadValue = code.stack[-2] *************** *** 1108,1113 **** _checkModifyDefaultArg(code, loadValue.data) ! code.popStackItems(2) ! _STORE_SUBSCR = _DELETE_SUBSCR = _pop2 def _CALL_FUNCTION(oparg, operand, codeSource, code) : --- 1156,1166 ---- _checkModifyDefaultArg(code, loadValue.data) ! code.popStackItems(n) ! ! def _DELETE_SUBSCR(oparg, operand, codeSource, code) : ! _popn(code, 2) ! ! def _STORE_SUBSCR(oparg, operand, codeSource, code) : ! _popn(code, 3) def _CALL_FUNCTION(oparg, operand, codeSource, code) : *************** *** 1136,1139 **** --- 1189,1197 ---- _makeConstant(code, oparg, Stack.makeList) + def _BUILD_CLASS(oparg, operand, codeSource, code) : + newValue = Stack.makeFuncReturnValue(code.stack[-1], types.ClassType) + code.popStackItems(3) + code.pushStack(newValue) + def _UNARY_CONVERT(oparg, operand, codeSource, code) : if len(code.stack) > 0 : *************** *** 1437,1462 **** def _checkStrException(code, varType, item): ! if varType is types.StringType and cfg().badExceptions: code.addWarning(msgs.RAISE_STR_EXCEPTION % item.data) ! def _RAISE_VARARGS(oparg, operand, codeSource, code) : code.addRaise() if oparg > 0 and len(code.stack) >= oparg: item = code.stack[-oparg] if item.type not in (Stack.TYPE_FUNC_RETURN, Stack.TYPE_UNKNOWN): if item.type is Stack.TYPE_GLOBAL: ! # FIXME: probably ought to try to handle raise module.Error ! e = None ! try: ! e = eval(item.data) ! except NameError: ! c = codeSource.module.classes.get(item.data) ! if c is not None: ! e = c.classObject ! else: ! v = codeSource.module.variables.get(item.data) ! if v is not None: ! _checkStrException(code, v.type, item) ! if e is not None and not _isexception(e) and cfg().badExceptions: code.addWarning(msgs.RAISE_BAD_EXCEPTION % item.data) else: --- 1495,1514 ---- def _checkStrException(code, varType, item): ! if varType is types.StringType: code.addWarning(msgs.RAISE_STR_EXCEPTION % item.data) ! def _RAISE_VARARGS(oparg, operand, codeSource, code) : code.addRaise() + if not cfg().badExceptions: + return + if oparg > 0 and len(code.stack) >= oparg: item = code.stack[-oparg] if item.type not in (Stack.TYPE_FUNC_RETURN, Stack.TYPE_UNKNOWN): if item.type is Stack.TYPE_GLOBAL: ! e, is_str = _getExceptionInfo(codeSource, item) ! if is_str: ! _checkStrException(code, e.type, item) ! elif e is not None and not _isexception(e): code.addWarning(msgs.RAISE_BAD_EXCEPTION % item.data) else: *************** *** 1496,1499 **** --- 1548,1552 ---- DISPATCH[ 85] = _EXEC_STMT DISPATCH[ 88] = _END_FINALLY + DISPATCH[ 89] = _BUILD_CLASS DISPATCH[ 90] = _STORE_NAME DISPATCH[ 91] = _DELETE_NAME Index: OP.py =================================================================== RCS file: /cvsroot/pychecker/pychecker/pychecker/OP.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** OP.py 4 Feb 2002 21:38:14 -0000 1.18 --- OP.py 30 Mar 2002 18:05:56 -0000 1.19 *************** *** 50,53 **** --- 50,55 ---- 'is not', 'exception match', 'BAD') + EXCEPT_COMPARE = _CMP_OP[10] + def getOperand(op, func_code, oparg) : if op in _HAS_NAME : Index: msgs.py =================================================================== RCS file: /cvsroot/pychecker/pychecker/pychecker/msgs.py,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** msgs.py 29 Mar 2002 15:18:04 -0000 1.33 --- msgs.py 30 Mar 2002 18:05:56 -0000 1.34 *************** *** 91,94 **** --- 91,96 ---- VAR_DELETED_BEFORE_SET = "Variable (%s) deleted before being set" + CATCH_BAD_EXCEPTION = "Catching a non-Exception object (%s)" + CATCH_STR_EXCEPTION = "Catching string exceptions are deprecated (%s)" RAISE_BAD_EXCEPTION = "Raising an exception on a non-Exception object (%s)" RAISE_STR_EXCEPTION = "Raising string exceptions are deprecated (%s)" |