You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by rl...@apache.org on 2016/06/21 02:41:29 UTC
[13/28] incubator-hawq git commit: HAWQ-837. Add python modules into
HAWQ code
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/pychecker-0.8.18/pychecker/CodeChecks.py
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/pychecker-0.8.18/pychecker/CodeChecks.py b/tools/bin/pythonSrc/pychecker-0.8.18/pychecker/CodeChecks.py
new file mode 100644
index 0000000..359642d
--- /dev/null
+++ b/tools/bin/pythonSrc/pychecker-0.8.18/pychecker/CodeChecks.py
@@ -0,0 +1,1969 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2001-2006, MetaSlash Inc. All rights reserved.
+# Portions Copyright (c) 2005, Google, Inc. All rights reserved.
+
+"""
+Find warnings in byte code from Python source files.
+"""
+
+import string
+import types
+
+from pychecker import msgs
+from pychecker import utils
+from pychecker import Warning
+from pychecker import OP
+from pychecker import Stack
+from pychecker import python
+
+__pychecker__ = 'no-argsused'
+
+
+def cfg() :
+ return utils.cfg()
+
+def getFunctionArgErr(func_name, argCount, minArgs, maxArgs):
+ err = None
+ if maxArgs == None:
+ if argCount < minArgs :
+ err = msgs.INVALID_ARG_COUNT2 % (func_name, argCount, minArgs)
+ elif argCount < minArgs or argCount > maxArgs:
+ if minArgs == maxArgs:
+ err = msgs.INVALID_ARG_COUNT1 % (func_name, argCount, minArgs)
+ else:
+ err = msgs.INVALID_ARG_COUNT3 % (func_name, argCount, minArgs, maxArgs)
+ return err
+
+def _checkFunctionArgCount(code, func_name, argCount, minArgs, maxArgs,
+ objectReference = 0) :
+ # there is an implied argument for object creation and self.xxx()
+ if objectReference :
+ minArgs = minArgs - 1
+ if maxArgs is not None :
+ maxArgs = maxArgs - 1
+
+ err = getFunctionArgErr(func_name, argCount, minArgs, maxArgs)
+ if err :
+ code.addWarning(err)
+
+def _checkFunctionArgs(code, func, objectReference, argCount, kwArgs,
+ check_arg_count = 1) :
+ func_name = func.function.func_code.co_name
+ if kwArgs :
+ args_len = func.function.func_code.co_argcount
+ arg_names = func.function.func_code.co_varnames[argCount:args_len]
+ if argCount < args_len and kwArgs[0] in arg_names:
+ if cfg().namedArgs :
+ code.addWarning(msgs.FUNC_USES_NAMED_ARGS % func_name)
+
+ # convert the named args into regular params, and really check
+ while argCount < args_len and kwArgs and kwArgs[0] in arg_names:
+ argCount = argCount + 1
+ kwArgs = kwArgs[1:]
+ _checkFunctionArgs(code, func, objectReference, argCount, kwArgs,
+ check_arg_count)
+ return
+
+ if not func.supportsKW :
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW % func_name)
+
+ if check_arg_count :
+ _checkFunctionArgCount(code, func_name, argCount,
+ func.minArgs, func.maxArgs, objectReference)
+
+def _getReferenceFromModule(module, identifier) :
+ func = module.functions.get(identifier, None)
+ if func is not None :
+ return func, None, 0
+
+ create = 0
+ c = module.classes.get(identifier, None)
+ if c is not None :
+ func = c.methods.get(utils.INIT, None)
+ create = 1
+ return func, c, create
+
+def _getFunction(module, stackValue) :
+ 'Return (function, class) from the stack value'
+
+ identifier = stackValue.data
+ if type(identifier) == types.StringType :
+ return _getReferenceFromModule(module, identifier)
+
+ # find the module this references
+ i, maxLen = 0, len(identifier)
+ while i < maxLen :
+ id = utils.safestr(identifier[i])
+ if module.classes.has_key(id) or module.functions.has_key(id) :
+ break
+ refModule = module.modules.get(id, None)
+ if refModule is not None :
+ module = refModule
+ else :
+ return None, None, 0
+ i = i + 1
+
+ # if we got to the end, there is only modules, nothing we can do
+ # we also can't handle if there is more than 2 items left
+ if i >= maxLen or (i+2) < maxLen :
+ return None, None, 0
+
+ if (i+1) == maxLen :
+ return _getReferenceFromModule(module, identifier[-1])
+
+ # we can't handle self.x.y
+ if (i+2) == maxLen and identifier[0] == cfg().methodArgName:
+ return None, None, 0
+
+ c = module.classes.get(identifier[-2], None)
+ if c is None :
+ return None, None, 0
+ return c.methods.get(identifier[-1], None), c, 0
+
+def _validateKwArgs(code, info, func_name, kwArgs):
+ if len(info) < 4:
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW % func_name)
+ elif not info[3]:
+ return
+
+ try:
+ # info could be from a builtin method which means that
+ # info[3] is not a list.
+ dummy = info[3][0]
+ except IndexError:
+ return
+
+ for arg in kwArgs:
+ if arg not in info[3]:
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW_ARG % (func_name, arg))
+
+def _checkBuiltin(code, loadValue, argCount, kwArgs, check_arg_count = 1) :
+ returnValue = Stack.makeFuncReturnValue(loadValue, argCount)
+ func_name = loadValue.data
+ if loadValue.type == Stack.TYPE_GLOBAL :
+ info = python.GLOBAL_FUNC_INFO.get(func_name, None)
+ if info is not None :
+ if func_name == 'input' and cfg().usesInput:
+ code.addWarning(msgs.USES_INPUT)
+ if cfg().constAttr and \
+ ((func_name == 'setattr' and argCount >= 2) or
+ (func_name == 'getattr' and argCount == 2)):
+ arg2 = code.stack[-argCount + 1]
+ if arg2.const:
+ # lambda with setattr and const is a common way of setting
+ # attributes, so allow it
+ if code.func.function.func_name != '<lambda>':
+ code.addWarning(msgs.USES_CONST_ATTR % func_name)
+
+ if kwArgs:
+ _validateKwArgs(code, info, func_name, kwArgs)
+ elif check_arg_count :
+ _checkFunctionArgCount(code, func_name, argCount,
+ info[1], info[2])
+ returnValue = Stack.Item(returnValue.data, info[0])
+ returnValue.setStringType(info[0])
+ elif type(func_name) == types.TupleType and len(func_name) <= 2 :
+ objType = code.typeMap.get(utils.safestr(func_name[0]), [])
+ if types.ListType in objType :
+ try :
+ if func_name[1] == 'append' and argCount > 1 :
+ code.addWarning(msgs.LIST_APPEND_ARGS % func_name[0])
+ check_arg_count = 0
+ except AttributeError :
+ # FIXME: why do we need to catch AttributeError???
+ pass
+ if len(objType) == 1 :
+ # if it's a builtin, check method
+ builtinType = python.BUILTIN_METHODS.get(objType[0])
+ if builtinType is not None :
+ methodInfo = builtinType.get(func_name[1])
+ # set func properly
+ if kwArgs :
+ _validateKwArgs(code, methodInfo, func_name[1], kwArgs)
+ elif methodInfo :
+ returnValue = Stack.Item(func_name[1], methodInfo[0])
+ returnValue.setStringType(methodInfo[0])
+ if check_arg_count and methodInfo is not None :
+ _checkFunctionArgCount(code, func_name[1], argCount,
+ methodInfo[1], methodInfo[2])
+
+ return returnValue
+
+_IMMUTABLE_LIST_METHODS = ('count', 'index',)
+_IMMUTABLE_DICT_METHODS = ('copy', 'get', 'has_key',
+ 'items', 'keys', 'values',
+ 'iteritems', 'iterkeys', 'itervalues')
+
+def _checkModifyDefaultArg(code, objectName, methodName=None) :
+ try :
+ value = code.func.defaultValue(objectName)
+ objectType = type(value)
+ if objectType in python.MUTABLE_TYPES :
+ if objectType == types.DictType and \
+ methodName in _IMMUTABLE_DICT_METHODS :
+ return
+ if objectType == types.ListType and \
+ methodName in _IMMUTABLE_LIST_METHODS :
+ return
+ code.addWarning(msgs.MODIFYING_DEFAULT_ARG % objectName)
+ except ValueError :
+ pass
+
+def _isexception(object) :
+ # FIXME: i have no idea why this function is necessary
+ # it seems that the issubclass() should work, but it doesn't always
+
+ if hasattr(object, 'type'):
+ if object.type == types.TupleType:
+ # if we have a tuple, we can't check the contents (not enough info)
+## for item in object.value:
+## if not _isexception(item):
+## return 0
+ return 1
+
+ try:
+ # try/except is necessary for globals like NotImplemented
+ if issubclass(object, Exception) :
+ return 1
+ # Python 2.5 added a BaseException to the hierarchy. That's
+ # really what we need to check if it exists.
+ if utils.pythonVersion() >= utils.PYTHON_2_5:
+ if issubclass(object, BaseException):
+ return 1
+ except TypeError:
+ return 0
+
+ for c in object.__bases__ :
+ if utils.startswith(utils.safestr(c), 'exceptions.') :
+ return 1
+ if len(c.__bases__) > 0 and _isexception(c) :
+ return 1
+ return 0
+
+def _checkStringFind(code, loadValue):
+ if len(loadValue.data) == 2 and loadValue.data[1] == 'find':
+ try:
+ if types.StringType in code.typeMap.get(loadValue.data[0], []):
+ op = code.nextOpInfo()[0]
+ if OP.IS_CONDITIONAL_JUMP(op) or OP.IS_NOT(op):
+ code.addWarning(msgs.BAD_STRING_FIND)
+ except TypeError:
+ # we don't care if loadValue.data[0] is not hashable
+ pass
+
+def _checkAbstract(refClass, code, name):
+ name_list = refClass.isAbstract()
+ if name_list:
+ name_list.sort()
+ names = string.join(name_list, ", ")
+ code.addWarning(msgs.METHODS_NEED_OVERRIDE % (names, name))
+
+_SEQUENCE_TYPES = (types.TupleType, types.ListType, types.StringType)
+try: _SEQUENCE_TYPES = _SEQUENCE_TYPES + (types.UnicodeType,)
+except AttributeError: pass
+
+# FIXME: this is not complete. errors will be caught only sometimes,
+# depending on the order the functions/methods are processed
+# in the dict. Need to be able to run through all functions
+# twice, but because the code sucks, this is not possible.
+def _checkReturnValueUse(code, func):
+ if func.returnValues is None:
+ return
+
+ err = None
+ opInfo = code.nextOpInfo()
+ if func.returnsNoValue():
+ # make sure we really know how to check for all the return types
+ for rv in func.returnValues:
+ if rv[1].type in _UNCHECKABLE_STACK_TYPES:
+ return
+
+ if not OP.POP_TOP(opInfo[0]):
+ err = msgs.USING_NONE_RETURN_VALUE % utils.safestr(func)
+ elif OP.UNPACK_SEQUENCE(opInfo[0]):
+ # verify unpacking into proper # of vars
+ varCount = opInfo[1]
+ stackRV = func.returnValues[0][1]
+ returnType = stackRV.getType({})
+ funcCount = stackRV.length
+ if returnType in _SEQUENCE_TYPES:
+ if varCount != funcCount and funcCount > 0:
+ err = msgs.WRONG_UNPACK_FUNCTION % (utils.safestr(func), funcCount, varCount)
+ elif returnType not in _UNCHECKABLE_STACK_TYPES:
+ err = msgs.UNPACK_NON_SEQUENCE % (utils.safestr(func), _getTypeStr(returnType))
+ if err:
+ code.addWarning(err)
+
+def _handleFunctionCall(codeSource, code, argCount, indexOffset = 0,
+ check_arg_count = 1) :
+ 'Checks for warnings, returns function called (may be None)'
+
+ if not code.stack :
+ return
+
+ kwArgCount = argCount >> utils.VAR_ARGS_BITS
+ argCount = argCount & utils.MAX_ARGS_MASK
+
+ # function call on stack is before the args, and keyword args
+ funcIndex = argCount + 2 * kwArgCount + 1 + indexOffset
+ if funcIndex > len(code.stack) :
+ funcIndex = 0
+ # to find on stack, we have to look backwards from top of stack (end)
+ funcIndex = -funcIndex
+
+ # store the keyword names/keys to check if using named arguments
+ kwArgs = []
+ if kwArgCount > 0 :
+ # loop backwards by 2 (keyword, value) in stack to find keyword args
+ for i in range(-2 - indexOffset, (-2 * kwArgCount - 1), -2) :
+ kwArgs.append(code.stack[i].data)
+ kwArgs.reverse()
+
+ loadValue = code.stack[funcIndex]
+ funcName = loadValue.getName()
+ returnValue = Stack.makeFuncReturnValue(loadValue, argCount)
+
+ if loadValue.isMethodCall(codeSource.classObject, cfg().methodArgName):
+ methodName = loadValue.data[1]
+ try :
+ m = codeSource.classObject.methods[methodName]
+ if m != None :
+ objRef = not m.isStaticMethod()
+ _checkFunctionArgs(code, m, objRef, argCount, kwArgs,
+ check_arg_count)
+ except KeyError :
+ sattr = codeSource.classObject.statics.get(methodName)
+ if sattr is not None :
+ funcName = sattr.getName()
+
+ if sattr is None and cfg().callingAttribute :
+ code.addWarning(msgs.INVALID_METHOD % methodName)
+
+ elif loadValue.type in (Stack.TYPE_ATTRIBUTE, Stack.TYPE_GLOBAL) and \
+ type(loadValue.data) in (types.StringType, types.TupleType) :
+ # apply(func, (args)), can't check # of args, so just return func
+ if loadValue.data == 'apply' :
+ loadValue = code.stack[funcIndex+1]
+ funcName = loadValue.getName()
+ else :
+ if cfg().modifyDefaultValue and \
+ type(loadValue.data) == types.TupleType :
+ _checkModifyDefaultArg(code, loadValue.data[0],
+ loadValue.data[1])
+
+ func, refClass, method = _getFunction(codeSource.module, loadValue)
+ if func == None and type(loadValue.data) == types.TupleType and \
+ len(loadValue.data) == 2 :
+ # looks like we are making a method call
+ data = loadValue.data
+ if type(data[0]) == types.StringType :
+ # do we know the type of the local variable?
+ varType = code.typeMap.get(data[0])
+ if varType is not None and len(varType) == 1 :
+ if hasattr(varType[0], 'methods') :
+ # it's a class & we know the type, get the method
+ func = varType[0].methods.get(data[1])
+ if func is not None :
+ method = 1
+
+ if cfg().abstractClasses and refClass and method:
+ _checkAbstract(refClass, code, funcName)
+
+ if cfg().stringFind:
+ _checkStringFind(code, loadValue)
+
+ if func != None :
+ if refClass and func.isClassMethod():
+ argCount = argCount + 1
+ _checkFunctionArgs(code, func, method, argCount, kwArgs,
+ check_arg_count)
+ # if this isn't a c'tor, we should check
+ if not (refClass and method) and cfg().checkReturnValues:
+ _checkReturnValueUse(code, func)
+
+ if refClass :
+ if method :
+ # c'tor, return the class as the type
+ returnValue = Stack.Item(loadValue, refClass)
+ elif func.isClassMethod():
+ # FIXME: do anything here?
+ pass
+ elif argCount > 0 and cfg().methodArgName and \
+ not func.isStaticMethod() and \
+ code.stack[funcIndex].type == Stack.TYPE_ATTRIBUTE and \
+ code.stack[funcIndex+1].data != cfg().methodArgName:
+ e = msgs.SELF_NOT_FIRST_ARG % (cfg().methodArgName, '')
+ code.addWarning(e)
+ elif refClass and method :
+ returnValue = Stack.Item(loadValue, refClass)
+ if (argCount > 0 or len(kwArgs) > 0) and \
+ not refClass.ignoreAttrs and \
+ not refClass.methods.has_key(utils.INIT) and \
+ not _isexception(refClass.classObject) :
+ code.addWarning(msgs.NO_CTOR_ARGS)
+ else :
+ returnValue = _checkBuiltin(code, loadValue, argCount, kwArgs,
+ check_arg_count)
+ if returnValue.type is types.NoneType and \
+ not OP.POP_TOP(code.nextOpInfo()[0]) :
+ name = utils.safestr(loadValue.data)
+ if type(loadValue.data) == types.TupleType :
+ name = string.join(loadValue.data, '.')
+ # lambda with setattr is a common way of setting
+ # attributes, so allow it
+ if name != 'setattr' \
+ or code.func.function.func_name != '<lambda>':
+ code.addWarning(msgs.USING_NONE_RETURN_VALUE % name)
+
+ code.stack = code.stack[:funcIndex] + [ returnValue ]
+ code.functionsCalled[funcName] = loadValue
+
+
+def _classHasAttribute(c, attr) :
+ return (c.methods.has_key(attr) or c.members.has_key(attr) or
+ hasattr(c.classObject, attr))
+
+def _checkClassAttribute(attr, c, code) :
+ if _classHasAttribute(c, attr) :
+ try :
+ del c.memberRefs[attr]
+ except KeyError :
+ pass
+ elif cfg().classAttrExists :
+ if attr not in cfg().missingAttrs:
+ code.addWarning(msgs.INVALID_CLASS_ATTR % attr)
+
+def _checkModuleAttribute(attr, module, code, ref) :
+ try:
+ if attr not in module.modules[ref].attributes and \
+ not utils.endswith(ref, '.' + attr) :
+ code.addWarning(msgs.INVALID_MODULE_ATTR % attr)
+ except (KeyError, TypeError):
+ # if ref isn't found, or ref isn't even hashable, we don't care
+ # we may not know, or ref could be something funky [e for e].method()
+ pass
+
+ try:
+ _checkClassAttribute(attr, module.classes[ref], code)
+ except (KeyError, TypeError):
+ # if ref isn't found, or ref isn't even hashable, we don't care
+ # we may not know, or ref could be something funky [e for e].method()
+ pass
+
+
+def _getGlobalName(name, func) :
+ # get the right name of global refs (for from XXX import YYY)
+ opModule = func.function.func_globals.get(name)
+ try :
+ if opModule and isinstance(opModule, types.ModuleType) :
+ name = opModule.__name__
+ except :
+ # we have to do this in case the class raises an access exception
+ # due to overriding __special__() methods
+ pass
+
+ return name
+
+
+def _checkNoEffect(code, ignoreStmtWithNoEffect=0):
+ if (not ignoreStmtWithNoEffect and
+ OP.POP_TOP(code.nextOpInfo()[0]) and cfg().noEffect):
+ code.addWarning(msgs.POSSIBLE_STMT_WITH_NO_EFFECT)
+
+def _makeConstant(code, index, factoryFunction) :
+ "Build a constant on the stack ((), [], or {})"
+ if index > 0 :
+ code.stack[-index:] = [ factoryFunction(code.stack[-index:]) ]
+ _checkNoEffect(code)
+ else :
+ code.pushStack(factoryFunction())
+
+
+def _hasGlobal(operand, module, func, main) :
+ return (func.function.func_globals.has_key(operand) or
+ main or module.moduleLineNums.has_key(operand) or
+ __builtins__.has_key(operand))
+
+def _checkGlobal(operand, module, func, code, err, main = 0) :
+ if not _hasGlobal(operand, module, func, main) :
+ code.addWarning(err % operand)
+ if not cfg().reportAllGlobals :
+ func.function.func_globals[operand] = operand
+
+
+def _handleComparison(stack, operand) :
+ num_ops = 2
+ if operand == 'exception match':
+ num_ops = 1
+
+ si = min(len(stack), num_ops)
+ compareValues = stack[-si:]
+ for _ in range(si, 2) :
+ compareValues.append(Stack.Item(None, None))
+ stack[-si:] = [ Stack.makeComparison(compareValues, operand) ]
+ return compareValues
+
+def _handleImport(code, operand, module, main, fromName) :
+ # FIXME: this function should be refactored/cleaned up
+ key = operand
+ tmpOperand = tmpFromName = operand
+ if fromName is not None :
+ tmpOperand = tmpFromName = fromName
+ key = (fromName, operand)
+
+ if cfg().deprecated:
+ try:
+ undeprecated = python.DEPRECATED_MODULES[tmpFromName]
+ except KeyError:
+ pass
+ else:
+ msg = msgs.USING_DEPRECATED_MODULE % tmpFromName
+ if undeprecated:
+ msg.data = msg.data + msgs.USE_INSTEAD % undeprecated
+ code.addWarning(msg)
+
+ if cfg().reimportSelf and tmpOperand == module.module.__name__ :
+ code.addWarning(msgs.IMPORT_SELF % tmpOperand)
+
+ modline1 = module.moduleLineNums.get(tmpOperand, None)
+ modline2 = module.moduleLineNums.get((tmpFromName, '*'), None)
+ key2 = (tmpFromName,)
+ if fromName is not None and operand != '*' :
+ key2 = (tmpFromName, operand)
+ modline3 = module.moduleLineNums.get(key2, None)
+
+ if modline1 is not None or modline2 is not None or modline3 is not None :
+ err = None
+
+ if fromName is None :
+ if modline1 is not None :
+ err = msgs.MODULE_IMPORTED_AGAIN % operand
+ elif cfg().mixImport :
+ err = msgs.MIX_IMPORT_AND_FROM_IMPORT % tmpFromName
+ else :
+ if modline3 is not None and operand != '*' :
+ err = 'from %s import %s' % (tmpFromName, operand)
+ err = msgs.MODULE_MEMBER_IMPORTED_AGAIN % err
+ elif modline1 is not None :
+ if cfg().mixImport and code.getLineNum() != modline1[1] :
+ err = msgs.MIX_IMPORT_AND_FROM_IMPORT % tmpFromName
+ else :
+ err = msgs.MODULE_MEMBER_ALSO_STAR_IMPORTED % fromName
+
+ # filter out warnings when files are different (ie, from X import ...)
+ if err is not None and cfg().moduleImportErrors :
+ bytes = module.main_code
+ if bytes is None or \
+ bytes.function.func_code.co_filename == code.func_code.co_filename :
+ code.addWarning(err)
+
+ if main :
+ fileline = (code.func_code.co_filename, code.getLineNum())
+ module.moduleLineNums[key] = fileline
+ if fromName is not None :
+ module.moduleLineNums[(fromName,)] = fileline
+
+
+def _handleImportFrom(code, operand, module, main) :
+ fromName = code.stack[-1].data
+ if utils.pythonVersion() < utils.PYTHON_2_0 and \
+ OP.POP_TOP(code.nextOpInfo()[0]):
+ code.popNextOp()
+ code.pushStack(Stack.Item(operand, types.ModuleType))
+ _handleImport(code, operand, module, main, fromName)
+
+
+# http://www.python.org/doc/current/lib/typesseq-strings.html
+_FORMAT_CONVERTERS = 'diouxXeEfFgGcrs'
+# NOTE: lLh are legal in the flags, but are ignored by python, we warn
+_FORMAT_FLAGS = '*#- +.' + string.digits
+
+def _getFormatInfo(format, code) :
+ vars = []
+
+ # first get rid of all the instances of %% in the string, they don't count
+ format = string.replace(format, "%%", "")
+ sections = string.split(format, '%')
+ percentFormatCount = formatCount = string.count(format, '%')
+ mappingFormatCount = 0
+
+ # skip the first item in the list, it's always empty
+ for section in sections[1:] :
+ orig_section = section
+ if not section:
+ w = msgs.INVALID_FORMAT % orig_section
+ w.data = w.data + ' (end of format string)'
+ code.addWarning(w)
+ continue
+
+ # handle dictionary formats
+ if section[0] == '(' :
+ mappingFormatCount = mappingFormatCount + 1
+ varname = string.split(section, ')')
+ if varname[1] == '' :
+ code.addWarning(msgs.INVALID_FORMAT % section)
+ vars.append(varname[0][1:])
+ section = varname[1]
+
+ if not section :
+ # no format data to check
+ continue
+
+ # FIXME: we ought to just define a regular expression to check
+ # formatRE = '[ #+-]*([0-9]*|*)(|.(|*|[0-9]*)[diouxXeEfFgGcrs].*'
+ stars = 0
+ for i in range(0, len(section)) :
+ if section[i] in _FORMAT_CONVERTERS :
+ break
+ if section[i] in _FORMAT_FLAGS :
+ if section[i] == '*' :
+ stars = stars + 1
+ if mappingFormatCount > 0 :
+ code.addWarning(msgs.USING_STAR_IN_FORMAT_MAPPING % section)
+
+ if stars > 2 :
+ code.addWarning(msgs.TOO_MANY_STARS_IN_FORMAT)
+
+ formatCount = formatCount + stars
+ if section[i] not in _FORMAT_CONVERTERS :
+ code.addWarning(msgs.INVALID_FORMAT % orig_section)
+
+ if mappingFormatCount > 0 and mappingFormatCount != percentFormatCount :
+ code.addWarning(msgs.CANT_MIX_MAPPING_IN_FORMATS)
+
+ return formatCount, vars
+
+def _getConstant(code, module, data) :
+ data = utils.safestr(data.data)
+ format = code.constants.get(data)
+ if format is not None :
+ return format
+
+ format = module.variables.get(data)
+ if format is not None and format.value is not None :
+ return format.value
+ return None
+
+_UNCHECKABLE_FORMAT_STACK_TYPES = \
+ (Stack.TYPE_UNKNOWN, Stack.TYPE_FUNC_RETURN, Stack.TYPE_ATTRIBUTE,
+ Stack.TYPE_GLOBAL, Stack.TYPE_EXCEPT)
+_UNCHECKABLE_STACK_TYPES = _UNCHECKABLE_FORMAT_STACK_TYPES + (types.NoneType,)
+
+def _getFormatString(code, codeSource) :
+ if len(code.stack) <= 1 :
+ return ''
+
+ format = code.stack[-2]
+ if format.type != types.StringType or not format.const :
+ format = _getConstant(code, codeSource.module, format)
+ if format is None or type(format) != types.StringType :
+ return ''
+ return format
+ return format.data
+
+
+def _getFormatWarnings(code, codeSource) :
+ format = _getFormatString(code, codeSource)
+ if not format :
+ return
+
+ args = 0
+ count, vars = _getFormatInfo(format, code)
+ topOfStack = code.stack[-1]
+ if topOfStack.isLocals() :
+ for varname in vars :
+ if not code.unusedLocals.has_key(varname) :
+ code.addWarning(msgs.NO_LOCAL_VAR % varname)
+ else :
+ code.unusedLocals[varname] = None
+ else :
+ stackItemType = topOfStack.getType(code.typeMap)
+ if ((stackItemType == types.DictType and len(vars) > 0) or
+ codeSource.func.isParam(topOfStack.data) or
+ stackItemType in _UNCHECKABLE_FORMAT_STACK_TYPES) :
+ return
+
+ if topOfStack.type == types.TupleType :
+ args = topOfStack.length
+ elif stackItemType == types.TupleType :
+ args = len(code.constants.get(topOfStack.data, (0,)))
+ else :
+ args = 1
+
+ if args and count != args :
+ code.addWarning(msgs.INVALID_FORMAT_COUNT % (count, args))
+
+def _checkAttributeType(code, stackValue, attr) :
+ if not cfg().checkObjectAttrs :
+ return
+
+ varTypes = code.typeMap.get(utils.safestr(stackValue.data), None)
+ if not varTypes :
+ return
+
+ # the value may have been converted on stack (`v`)
+ other_types = []
+ if stackValue.type not in varTypes :
+ other_types = [stackValue.type]
+
+ for varType in varTypes + other_types :
+ # ignore built-in types that have no attributes
+ if python.METHODLESS_OBJECTS.has_key(varType) :
+ continue
+
+ attrs = python.BUILTIN_ATTRS.get(varType, None)
+ if attrs is not None :
+ if attr in attrs :
+ return
+ continue
+
+ if hasattr(varType, 'ignoreAttrs') :
+ if varType.ignoreAttrs or _classHasAttribute(varType, attr) :
+ return
+ elif not hasattr(varType, 'attributes') or attr in varType.attributes :
+ return
+
+ code.addWarning(msgs.OBJECT_HAS_NO_ATTR % (stackValue.data, attr))
+
+
+def _getTypeStr(t):
+ returnStr = utils.safestr(t)
+ strs = string.split(returnStr, "'")
+ try:
+ if len(strs) == 3:
+ returnStr = strs[-2]
+ except IndexError:
+ pass
+ return returnStr
+
+
+def _getLineNum(co, instr_index):
+ co_lnotab = co.co_lnotab
+ lineno = co.co_firstlineno
+ addr = 0
+ for lnotab_index in range(0, len(co_lnotab), 2):
+ addr = addr + ord(co_lnotab[lnotab_index])
+ if addr > instr_index:
+ return lineno
+ lineno = lineno + ord(co_lnotab[lnotab_index+1])
+ return lineno
+
+
+class Code :
+ 'Hold all the code state information necessary to find warnings'
+
+ def __init__(self) :
+ self.bytes = None
+ self.func = None
+ self.func_code = None
+ self.index = 0
+ self.indexList = []
+ self.extended_arg = 0
+ self.lastLineNum = 0
+ self.maxCode = 0
+ self.has_except = 0
+ self.try_finally_first = 0
+ self.starts_and_ends_with_finally = 0
+
+ self.returnValues = []
+ self.raiseValues = []
+ self.stack = []
+
+ self.unpackCount = 0
+ self.loops = 0
+ self.branches = {}
+
+ self.warnings = []
+
+ self.globalRefs = {}
+ self.unusedLocals = {}
+ self.deletedLocals = {}
+ self.functionsCalled = {}
+ self.typeMap = {}
+ self.constants = {}
+ self.codeObjects = {}
+
+ def init(self, func) :
+ self.func = func
+ self.func_code, self.bytes, self.index, self.maxCode, self.extended_arg = \
+ OP.initFuncCode(func.function)
+ self.lastLineNum = self.func_code.co_firstlineno
+ self.returnValues = []
+
+ # initialize the arguments to unused
+ for arg in func.arguments() :
+ self.unusedLocals[arg] = 0
+ self.typeMap[arg] = [ Stack.TYPE_UNKNOWN ]
+
+ def getLineNum(self):
+ line = self.lastLineNum
+ # if we don't have linenum info, calc it from co_lntab & index
+ if line == self.func_code.co_firstlineno:
+ # FIXME: this could be optimized, if we kept last line info
+ line = _getLineNum(self.func_code, self.index - 1)
+ return line
+
+ def getWarning(self, err, line = None) :
+ if line is None :
+ line = self.getLineNum()
+ return Warning.Warning(self.func_code, line, err)
+
+ def addWarning(self, err, line = None) :
+ w = err
+ if not isinstance(w, Warning.Warning):
+ w = self.getWarning(err, line)
+ self.warnings.append(w)
+
+ def popNextOp(self) :
+ self.indexList.append(self.index)
+ info = OP.getInfo(self.bytes, self.index, self.extended_arg)
+ op, oparg, self.index, self.extended_arg = info
+ if op < OP.HAVE_ARGUMENT :
+ utils.debug(" %d %s" % (self.indexList[-1], OP.name[op]))
+ operand = None
+ else :
+ operand = OP.getOperand(op, self.func_code, oparg)
+ self.label = label = OP.getLabel(op, oparg, self.index)
+ utils.debug(" %d %s" % (self.indexList[-1], OP.name[op]), oparg, operand)
+ if label != None :
+ self.addBranch(label)
+
+ return op, oparg, operand
+
+ def nextOpInfo(self, offset = 0) :
+ try :
+ return OP.getInfo(self.bytes, self.index + offset, 0)[0:3]
+ except IndexError :
+ return -1, 0, -1
+
+ def getFirstOp(self) :
+ # find the first real op, maybe we should not check if params are used
+ i = extended_arg = 0
+ while i < self.maxCode :
+ op, oparg, i, extended_arg = OP.getInfo(self.bytes, i, extended_arg)
+ if not OP.LINE_NUM(op) :
+ if not (OP.LOAD_CONST(op) or OP.LOAD_GLOBAL(op)) :
+ return op
+ raise RuntimeError('Could not find first opcode in function')
+
+ def pushStack(self, item, ignoreStmtWithNoEffect=0):
+ self.stack.append(item)
+ _checkNoEffect(self, ignoreStmtWithNoEffect)
+
+ def popStack(self) :
+ if self.stack :
+ del self.stack[-1]
+
+ def popStackItems(self, count) :
+ stackLen = len(self.stack)
+ if stackLen > 0 :
+ count = min(count, stackLen)
+ del self.stack[-count:]
+
+ def unpack(self) :
+ if self.unpackCount :
+ self.unpackCount = self.unpackCount - 1
+ else :
+ self.popStack()
+
+ def __getStringStackType(self, data) :
+ try :
+ return data.getType({})
+ except AttributeError :
+ return Stack.TYPE_UNKNOWN
+
+ def __getStackType(self) :
+ if not self.stack :
+ return Stack.TYPE_UNKNOWN
+
+ if not self.unpackCount :
+ return self.__getStringStackType(self.stack[-1])
+
+ data = self.stack[-1].data
+ if type(data) == types.TupleType :
+ try :
+ return self.__getStringStackType(data[len(data)-self.unpackCount])
+ except IndexError :
+ # happens when unpacking a var for which we don't know the size
+ pass
+
+ return Stack.TYPE_UNKNOWN
+
+ def setType(self, name) :
+ valueList = self.typeMap.get(name, [])
+ newType = self.__getStackType()
+ # longs are being merged with ints, assume they are the same
+ # comparisons are really ints anyways
+ if newType in (types.LongType, Stack.TYPE_COMPARISON):
+ newType = types.IntType
+ if newType not in valueList :
+ valueList.append(newType)
+
+ # need to ignore various types (Unknown, Func return values, etc)
+ # also ignore None, don't care if they use it and a real type
+ if valueList and newType not in _UNCHECKABLE_STACK_TYPES and \
+ cfg().inconsistentTypes:
+ oldTypes = []
+ # only add types to the value list that are "interesting"
+ for typeToAdd in valueList:
+ if typeToAdd not in _UNCHECKABLE_STACK_TYPES and \
+ typeToAdd != newType:
+ oldTypes.append(_getTypeStr(typeToAdd))
+ # do we have any "interesting" old types? if so, warn
+ if oldTypes:
+ self.addWarning(msgs.INCONSISTENT_TYPE % \
+ (name, oldTypes, _getTypeStr(newType)))
+ self.typeMap[name] = valueList
+
+ def addReturn(self) :
+ if len(self.stack) > 0 :
+ value = (self.getLineNum(), self.stack[-1], self.nextOpInfo()[2])
+ self.returnValues.append(value)
+ self.popStack()
+
+ def addRaise(self) :
+ self.raiseValues.append((self.getLineNum(), None, self.nextOpInfo()[2]))
+
+ def addBranch(self, label) :
+ if label is not None :
+ self.branches[label] = self.branches.get(label, 0) + 1
+
+ def removeBranch(self, label) :
+ branch = self.branches.get(label, None)
+ if branch is not None :
+ if branch == 1 :
+ del self.branches[label]
+ else :
+ self.branches[label] = branch - 1
+
+ def remove_unreachable_code(self, label) :
+ if len(self.indexList) >= 2 :
+ index = self.indexList[-2]
+ if index >= 0 and OP.POP_BLOCK(ord(self.bytes[index])) :
+ index = self.indexList[-3]
+ if index >= 0 :
+ op = ord(self.bytes[index])
+ if OP.RETURN_VALUE(op) or OP.RAISE_VARARGS(op) or \
+ OP.END_FINALLY(ord(self.bytes[label-1])) :
+ self.removeBranch(label)
+
+ def updateCheckerArgs(self, operand) :
+ rc = utils.shouldUpdateArgs(operand)
+ if rc :
+ utils.updateCheckerArgs(self.stack[-1].data, self.func_code,
+ self.getLineNum(), self.warnings)
+ return rc
+
+ def updateModuleLineNums(self, module, operand) :
+ filelist = (self.func_code.co_filename, self.getLineNum())
+ module.moduleLineNums[operand] = filelist
+
+
+class CodeSource :
+ 'Holds source information about a code block (module, class, func, etc)'
+ def __init__(self, module, func, c, main, in_class, code) :
+ self.module = module
+ self.func = func
+ self.classObject = c
+ self.main = main
+ self.in_class = in_class
+ self.code = code
+ self.calling_code = []
+
+def _checkException(code, name) :
+ if code.stack and code.stack[-1].type == Stack.TYPE_EXCEPT :
+ if __builtins__.has_key(name) :
+ code.addWarning(msgs.SET_EXCEPT_TO_BUILTIN % name)
+
+def _checkAssign(code, name):
+ if name in _BAD_ASSIGN_NAMES:
+ code.addWarning(msgs.SHOULDNT_ASSIGN_BUILTIN % name)
+ else:
+ cap = string.capitalize(name)
+ if cap in _BAD_ASSIGN_NAMES:
+ code.addWarning(msgs.SHOULDNT_ASSIGN_NAME % (name, cap))
+
+def _checkVariableOperationOnItself(code, lname, msg):
+ if code.stack and code.stack[-1].getName() == lname:
+ code.addWarning(msg % lname)
+
+def _checkFutureKeywords(code, varname) :
+ kw = python.FUTURE_KEYWORDS.get(varname)
+ if kw is not None :
+ code.addWarning(msgs.USING_KEYWORD % (varname, kw))
+
+def _STORE_NAME(oparg, operand, codeSource, code) :
+ if not code.updateCheckerArgs(operand) :
+ _checkFutureKeywords(code, operand)
+ module = codeSource.module
+ if not codeSource.in_class :
+ _checkShadowBuiltin(code, operand)
+ if not codeSource.calling_code :
+ _checkGlobal(operand, module, codeSource.func, code,
+ msgs.GLOBAL_DEFINED_NOT_DECLARED, codeSource.main)
+ else :
+ if code.stack :
+ codeSource.classObject.statics[operand] = code.stack[-1]
+ codeSource.classObject.lineNums[operand] = code.getLineNum()
+
+ var = module.variables.get(operand)
+ if var is not None and code.stack and code.stack[-1].const :
+ var.value = code.stack[-1].data
+
+ if code.unpackCount :
+ code.unpackCount = code.unpackCount - 1
+ else:
+ _checkAssign(code, operand)
+ _checkException(code, operand)
+ code.popStack()
+ if not module.moduleLineNums.has_key(operand) and codeSource.main :
+ code.updateModuleLineNums(module, operand)
+
+_STORE_GLOBAL = _STORE_NAME
+
+def _checkLoadGlobal(codeSource, code, varname) :
+ _checkFutureKeywords(code, varname)
+ should_check = 1
+ if code.func_code.co_name == utils.LAMBDA :
+ # this could really be a local reference, check first
+ if not codeSource.main and codeSource.calling_code:
+ func = getattr(codeSource.calling_code[-1], 'function', None)
+ if func is not None and varname in func.func_code.co_varnames :
+ _handleLoadLocal(code, codeSource, varname)
+ should_check = 0
+
+ if should_check :
+ # if a global var starts w/__ and the global is referenced in a class
+ # we have to strip off the _class-name, to get the original name
+ if codeSource.classObject and \
+ utils.startswith(varname, '_' + codeSource.classObject.name + '__'):
+ varname = varname[len(codeSource.classObject.name)+1:]
+
+ # make sure we remember each global ref to check for unused
+ code.globalRefs[_getGlobalName(varname, codeSource.func)] = varname
+ if not codeSource.in_class :
+ _checkGlobal(varname, codeSource.module, codeSource.func,
+ code, msgs.INVALID_GLOBAL)
+
+def _LOAD_NAME(oparg, operand, codeSource, code) :
+ _checkLoadGlobal(codeSource, code, operand)
+
+ # if there was from XXX import *, _* names aren't imported
+ if codeSource.module.modules.has_key(operand) and \
+ hasattr(codeSource.module.module, operand) :
+ operand = getattr(codeSource.module.module, operand).__name__
+
+ opType, const = Stack.TYPE_GLOBAL, 0
+ if operand == 'None' :
+ opType, const = types.NoneType, 0
+ elif operand == 'Ellipsis' :
+ opType, const = types.EllipsisType, 1
+ code.pushStack(Stack.Item(operand, opType, const))
+
+_LOAD_GLOBAL = _LOAD_NAME
+
+def _LOAD_DEREF(oparg, operand, codeSource, code) :
+ if type(oparg) == types.IntType :
+ func_code = code.func_code
+ try:
+ argname = func_code.co_cellvars[oparg]
+ except IndexError:
+ argname = func_code.co_freevars[oparg - len(func_code.co_cellvars)]
+ code.pushStack(Stack.Item(argname, types.StringType))
+ if code.func_code.co_name != utils.LAMBDA :
+ code.unusedLocals[argname] = None
+ else :
+ _LOAD_GLOBAL(oparg, operand, codeSource, code)
+
+_LOAD_CLOSURE = _LOAD_DEREF
+
+def _DELETE_NAME(oparg, operand, codeSource, code) :
+ _checkLoadGlobal(codeSource, code, operand)
+ # FIXME: handle deleting global multiple times
+_DELETE_GLOBAL = _DELETE_NAME
+
+def _make_const(value):
+ if type(value) == types.TupleType:
+ return Stack.makeTuple(map(_make_const, value))
+ return Stack.Item(value, type(value), 1)
+
+def _LOAD_CONST(oparg, operand, codeSource, code) :
+ code.pushStack(_make_const(operand))
+ if type(operand) == types.CodeType :
+ name = operand.co_name
+ obj = code.codeObjects.get(name, None)
+ if name == utils.LAMBDA :
+ # use a unique key, so we can have multiple lambdas
+ code.codeObjects[code.index] = operand
+ elif obj is None :
+ code.codeObjects[name] = operand
+ elif cfg().redefiningFunction :
+ code.addWarning(msgs.REDEFINING_ATTR % (name, obj.co_firstlineno))
+
+
+def _checkLocalShadow(code, module, varname) :
+ if module.variables.has_key(varname) and cfg().shadows :
+ line = module.moduleLineNums.get(varname, ('<unknown>', 0))
+ w = code.getWarning(msgs.LOCAL_SHADOWS_GLOBAL % (varname, line[1]))
+ if line[0] != w.file:
+ w.err = '%s in file %s' % (w.err, line[0])
+ code.addWarning(w)
+
+def _checkShadowBuiltin(code, varname) :
+ if __builtins__.has_key(varname) and varname[0] != '_' and \
+ cfg().shadowBuiltins:
+ code.addWarning(msgs.VARIABLE_SHADOWS_BUILTIN % varname)
+
+def _checkLoadLocal(code, codeSource, varname, deletedWarn, usedBeforeSetWarn) :
+ _checkFutureKeywords(code, varname)
+ deletedLine = code.deletedLocals.get(varname)
+ if deletedLine :
+ code.addWarning(deletedWarn % (varname, deletedLine))
+ elif not code.unusedLocals.has_key(varname) and \
+ not codeSource.func.isParam(varname) :
+ code.addWarning(usedBeforeSetWarn % varname)
+ code.unusedLocals[varname] = None
+ _checkLocalShadow(code, codeSource.module, varname)
+
+def _handleLoadLocal(code, codeSource, varname) :
+ _checkLoadLocal(code, codeSource, varname,
+ msgs.LOCAL_DELETED, msgs.VAR_USED_BEFORE_SET)
+
+def _LOAD_FAST(oparg, operand, codeSource, code) :
+ code.pushStack(Stack.Item(operand, type(operand)))
+ _handleLoadLocal(code, codeSource, operand)
+
+def _STORE_FAST(oparg, operand, codeSource, code) :
+ if not code.updateCheckerArgs(operand) :
+ _checkFutureKeywords(code, operand)
+ if code.stack and code.stack[-1].type == types.StringType and \
+ not code.stack[-1].const:
+ _checkVariableOperationOnItself(code, operand,
+ msgs.SET_VAR_TO_ITSELF)
+ code.setType(operand)
+ if not code.unpackCount and code.stack and \
+ (code.stack[-1].const or code.stack[-1].type == types.TupleType) :
+ if code.constants.has_key(operand) :
+ del code.constants[operand]
+ else :
+ code.constants[operand] = code.stack[-1].data
+
+ _checkLocalShadow(code, codeSource.module, operand)
+ _checkShadowBuiltin(code, operand)
+ _checkAssign(code, operand)
+ _checkException(code, operand)
+ if code.deletedLocals.has_key(operand) :
+ del code.deletedLocals[operand]
+ if not code.unusedLocals.has_key(operand) :
+ errLine = code.getLineNum()
+ if code.unpackCount and not cfg().unusedLocalTuple :
+ errLine = -errLine
+ code.unusedLocals[operand] = errLine
+ code.unpack()
+
+def _DELETE_FAST(oparg, operand, codeSource, code) :
+ _checkLoadLocal(code, codeSource, operand,
+ msgs.LOCAL_ALREADY_DELETED, msgs.VAR_DELETED_BEFORE_SET)
+ code.deletedLocals[operand] = code.getLineNum()
+
+def _checkAttribute(top, operand, codeSource, code) :
+ if top.data == cfg().methodArgName and codeSource.classObject != None :
+ _checkClassAttribute(operand, codeSource.classObject, code)
+ elif type(top.type) == types.StringType or top.type == types.ModuleType :
+ _checkModuleAttribute(operand, codeSource.module, code, top.data)
+ else :
+ _checkAttributeType(code, top, operand)
+
+def _checkExcessiveReferences(code, top, extraAttr = None) :
+ if cfg().maxReferences <= 0 :
+ return
+
+ try :
+ data = top.data
+ if extraAttr is not None :
+ data = data + (extraAttr,)
+
+ maxReferences = cfg().maxReferences
+ if data[0] == cfg().methodArgName:
+ maxReferences = maxReferences + 1
+ if len(data) > maxReferences :
+ name = string.join(top.data, '.')
+ code.addWarning(msgs.TOO_MANY_REFERENCES % (maxReferences, name))
+ except TypeError :
+ pass
+
+def _checkDeprecated(code, identifierTuple):
+ # check deprecated module.function
+ try:
+ name = string.join(identifierTuple, '.')
+ undeprecated = python.DEPRECATED_ATTRS[name]
+ except (KeyError, TypeError):
+ pass
+ else:
+ msg = msgs.USING_DEPRECATED_ATTR % name
+ if undeprecated:
+ msg.data = msg.data + msgs.USE_INSTEAD % undeprecated
+ code.addWarning(msg)
+
+def _LOAD_ATTR(oparg, operand, codeSource, code) :
+ if len(code.stack) > 0 :
+ top = code.stack[-1]
+ _checkAttribute(top, operand, codeSource, code)
+ top.addAttribute(operand)
+
+ if len(top.data) == 2:
+ if cfg().deprecated:
+ _checkDeprecated(code, top.data)
+
+ try:
+ insecure = python.SECURITY_FUNCS.get(top.data[0])
+ except TypeError:
+ pass
+ else:
+ if insecure and insecure.has_key(operand):
+ func = string.join(top.data, '.')
+ code.addWarning(msgs.USING_INSECURE_FUNC % func)
+
+ nextOp = code.nextOpInfo()[0]
+ if not OP.LOAD_ATTR(nextOp) :
+ if OP.POP_TOP(nextOp) and cfg().noEffect:
+ code.addWarning(msgs.POSSIBLE_STMT_WITH_NO_EFFECT)
+ else :
+ _checkExcessiveReferences(code, top)
+
+def _ok_to_set_attr(classObject, basename, attr) :
+ return (cfg().onlyCheckInitForMembers and classObject != None and
+ basename == cfg().methodArgName and
+ not _classHasAttribute(classObject, attr))
+
+def _STORE_ATTR(oparg, operand, codeSource, code) :
+ if code.stack :
+ top = code.stack.pop()
+ top_name = '%s.%s' % (top.getName(), operand)
+ try:
+ # FIXME: this is a hack to handle code like:
+ # a.a = [x for x in range(2) if x > 1]
+ previous = code.stack[-1]
+ except IndexError:
+ previous = None
+ if top.type in (types.StringType, Stack.TYPE_ATTRIBUTE) and \
+ previous and previous.type == Stack.TYPE_ATTRIBUTE:
+ _checkVariableOperationOnItself(code, top_name,
+ msgs.SET_VAR_TO_ITSELF)
+ _checkExcessiveReferences(code, top, operand)
+ if _ok_to_set_attr(codeSource.classObject, top.data, operand) :
+ code.addWarning(msgs.INVALID_SET_CLASS_ATTR % operand)
+ code.unpack()
+
+def _DELETE_ATTR(oparg, operand, codeSource, code) :
+ if len(code.stack) > 0 :
+ _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:
+ try:
+ c = codeSource.module.classes.get(item.data)
+ except TypeError: # item.data may not be hashable (e.g., list)
+ return e, 0
+
+ if c is not None:
+ e = c.classObject
+ else:
+ v = codeSource.module.variables.get(item.data)
+ if v is not None:
+ return v, (v.type == types.StringType)
+ 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)
+
+_BOOL_NAMES = ('True', 'False')
+_BAD_ASSIGN_NAMES = _BOOL_NAMES + ('None',)
+
+def _checkBoolean(code, checks):
+ for item in checks:
+ try:
+ data = string.capitalize(item.data)
+ if item.type is Stack.TYPE_GLOBAL and data in _BOOL_NAMES:
+ code.addWarning(msgs.BOOL_COMPARE % item.data)
+ except (AttributeError, TypeError):
+ # TypeError is necessary for Python 1.5.2
+ pass # ignore items that are not a StackItem or a string
+
+def _COMPARE_OP(oparg, operand, codeSource, code) :
+ compareValues = _handleComparison(code.stack, operand)
+ if oparg == OP.EXCEPT_COMPARISON:
+ _handleExceptionChecks(codeSource, code, compareValues)
+ elif oparg < OP.IN_COMPARISON: # '<', '<=', '==', '!=', '>', '>='
+ _checkBoolean(code, compareValues)
+ elif oparg < OP.IS_COMPARISON: # 'in', 'not in'
+ # TODO: any checks that should be done here?
+ pass
+ elif cfg().isLiteral:
+ # X is Y or X is not Y comparison
+ second_arg = code.stack[-1].data[2]
+ # FIXME: how should booleans be handled, need to think about it
+## if second_arg.const or (second_arg.type == Stack.TYPE_GLOBAL and
+## second_arg.data in ['True', 'False']):
+ if second_arg.const and second_arg.data is not None:
+ data = second_arg.data
+ if second_arg.type is types.DictType:
+ data = {}
+ not_str = ''
+ if oparg != OP.IS_COMPARISON:
+ not_str = ' not'
+ code.addWarning(msgs.IS_LITERAL % (not_str, data))
+
+ _checkNoEffect(code)
+
+def _IMPORT_NAME(oparg, operand, codeSource, code) :
+ code.pushStack(Stack.Item(operand, types.ModuleType))
+ nextOp = code.nextOpInfo()[0]
+ if not OP.IMPORT_FROM(nextOp) and not OP.IMPORT_STAR(nextOp) :
+ _handleImport(code, operand, codeSource.module, codeSource.main, None)
+
+def _IMPORT_FROM(oparg, operand, codeSource, code) :
+ _handleImportFrom(code, operand, codeSource.module, codeSource.main)
+ # this is necessary for python 1.5 (see STORE_GLOBAL/NAME)
+ if utils.pythonVersion() < utils.PYTHON_2_0 :
+ code.popStack()
+ if not codeSource.main :
+ code.unusedLocals[operand] = None
+ elif not codeSource.module.moduleLineNums.has_key(operand) :
+ code.updateModuleLineNums(codeSource.module, operand)
+
+def _IMPORT_STAR(oparg, operand, codeSource, code) :
+ _handleImportFrom(code, '*', codeSource.module, codeSource.main)
+
+# Python 2.3 introduced some optimizations that create problems
+# this is a utility for ignoring these cases
+def _shouldIgnoreCodeOptimizations(code, bytecodes, offset, length=None):
+ if utils.pythonVersion() < utils.PYTHON_2_3:
+ return 0
+
+ if length is None:
+ length = offset - 1
+ try:
+ start = code.index - offset
+ return bytecodes == code.bytes[start:start+length]
+ except IndexError:
+ return 0
+
+# In Python 2.3, a, b = 1,2 generates this code:
+# ...
+# ROT_TWO
+# JUMP_FORWARD 2
+# DUP_TOP
+# POP_TOP
+#
+# which generates a Possible stmt w/no effect
+
+# ROT_TWO = 2; JUMP_FORWARD = 110; 2, 0 is the offset (2)
+_IGNORE_SEQ = '%c%c%c%c' % (2, 110, 2, 0)
+def _shouldIgnoreNoEffectWarning(code):
+ return _shouldIgnoreCodeOptimizations(code, _IGNORE_SEQ, 5)
+
+def _DUP_TOP(oparg, operand, codeSource, code) :
+ if len(code.stack) > 0 :
+ code.pushStack(code.stack[-1], _shouldIgnoreNoEffectWarning(code))
+
+def _popn(code, n) :
+ if len(code.stack) >= 2 :
+ loadValue = code.stack[-2]
+ if cfg().modifyDefaultValue and loadValue.type == types.StringType :
+ _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) :
+ _handleFunctionCall(codeSource, code, oparg)
+
+def _CALL_FUNCTION_VAR(oparg, operand, codeSource, code) :
+ _handleFunctionCall(codeSource, code, oparg, 1, 0)
+
+def _CALL_FUNCTION_KW(oparg, operand, codeSource, code) :
+ _handleFunctionCall(codeSource, code, oparg, 1)
+
+def _CALL_FUNCTION_VAR_KW(oparg, operand, codeSource, code) :
+ _handleFunctionCall(codeSource, code, oparg, 2, 0)
+
+def _MAKE_FUNCTION(oparg, operand, codeSource, code) :
+ newValue = Stack.makeFuncReturnValue(code.stack[-1], oparg)
+ code.popStackItems(oparg+1)
+ code.pushStack(newValue)
+
+def _MAKE_CLOSURE(oparg, operand, codeSource, code) :
+ _MAKE_FUNCTION(max(0, oparg - 1), operand, codeSource, code)
+
+def _BUILD_MAP(oparg, operand, codeSource, code) :
+ _makeConstant(code, oparg, Stack.makeDict)
+def _BUILD_TUPLE(oparg, operand, codeSource, code) :
+ _makeConstant(code, oparg, Stack.makeTuple)
+def _BUILD_LIST(oparg, operand, codeSource, code) :
+ _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 _LIST_APPEND(oparg, operand, codeSource, code):
+ code.popStackItems(2)
+
+def _modifyStackName(code, suffix):
+ if code.stack:
+ tos = code.stack[-1]
+ tos_type = type(tos.data)
+ if tos_type == types.StringType:
+ tos.data = tos.data + suffix
+ elif tos_type == types.TupleType and \
+ type(tos.data[-1]) == types.StringType:
+ tos.data = tos.data[:-1] + (tos.data[-1] + suffix,)
+
+def _UNARY_CONVERT(oparg, operand, codeSource, code) :
+ if code.stack:
+ stackValue = code.stack[-1]
+ if stackValue.data == cfg().methodArgName and \
+ stackValue.const == 0 and codeSource.classObject is not None and \
+ codeSource.func.function.func_name == '__repr__' :
+ code.addWarning(msgs.USING_SELF_IN_REPR)
+ stackValue.data = utils.safestr(stackValue.data)
+ stackValue.type = types.StringType
+ _modifyStackName(code, '-repr')
+
+def _UNARY_POSITIVE(oparg, operand, codeSource, code) :
+ if OP.UNARY_POSITIVE(code.nextOpInfo()[0]) :
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '++')
+ code.popNextOp()
+ elif cfg().unaryPositive and code.stack and not code.stack[-1].const :
+ code.addWarning(msgs.UNARY_POSITIVE_HAS_NO_EFFECT)
+ _modifyStackName(code, '-pos')
+
+def _UNARY_NEGATIVE(oparg, operand, codeSource, code) :
+ if OP.UNARY_NEGATIVE(code.nextOpInfo()[0]) :
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '--')
+ _modifyStackName(code, '-neg')
+
+def _UNARY_NOT(oparg, operand, codeSource, code) :
+ _modifyStackName(code, '-not')
+
+def _UNARY_INVERT(oparg, operand, codeSource, code) :
+ if OP.UNARY_INVERT(code.nextOpInfo()[0]) :
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '~~')
+ _modifyStackName(code, '-invert')
+
+
+def _popStackRef(code, operand, count = 2) :
+ code.popStackItems(count)
+ code.pushStack(Stack.Item(operand, Stack.TYPE_UNKNOWN))
+
+def _popModifiedStack(code, suffix=' '):
+ code.popStack()
+ _modifyStackName(code, suffix)
+
+def _pop(oparg, operand, codeSource, code) :
+ code.popStack()
+_POP_TOP = _PRINT_ITEM = _pop
+
+def _popModified(oparg, operand, codeSource, code):
+ _popModifiedStack(code)
+
+def _BINARY_RSHIFT(oparg, operand, codeSource, code):
+ _coerce_type(code)
+ _popModified(oparg, operand, codeSource, code)
+_BINARY_LSHIFT = _BINARY_RSHIFT
+
+def _checkModifyNoOp(code, op, msg=msgs.MODIFY_VAR_NOOP, modifyStack=1):
+ stack = code.stack
+ if len(stack) >= 2:
+ if (stack[-1].type != Stack.TYPE_UNKNOWN and
+ stack[-2].type != Stack.TYPE_UNKNOWN):
+ name = stack[-1].getName()
+ if name != Stack.TYPE_UNKNOWN and name == stack[-2].getName():
+ code.addWarning(msg % (name, op, name))
+
+ if modifyStack:
+ code.popStack()
+ stack[-1].const = 0
+ _modifyStackName(code, op)
+
+def _BINARY_AND(oparg, operand, codeSource, code):
+ # Don't modify the stack, since _coerce_type() will do it.
+ _checkModifyNoOp(code, '&', modifyStack=0)
+ _coerce_type(code)
+
+def _BINARY_OR(oparg, operand, codeSource, code):
+ # Don't modify the stack, since _coerce_type() will do it.
+ _checkModifyNoOp(code, '|', modifyStack=0)
+ _coerce_type(code)
+
+def _BINARY_XOR(oparg, operand, codeSource, code):
+ # Don't modify the stack, since _coerce_type() will do it.
+ _checkModifyNoOp(code, '^', msgs.XOR_VAR_WITH_ITSELF, modifyStack=0)
+ _coerce_type(code)
+
+def _PRINT_ITEM_TO(oparg, operand, codeSource, code) :
+ code.popStackItems(2)
+
+try:
+ ComplexType = types.ComplexType
+except NameError:
+ ComplexType = types.FloatType # need some numeric type here
+
+_NUMERIC_TYPES = (types.IntType, types.FloatType, ComplexType)
+
+# FIXME: This is pathetically weak, need to handle more types
+def _coerce_type(code) :
+ _checkNoEffect(code)
+ newItem = Stack.Item('<stack>', Stack.TYPE_UNKNOWN)
+ if len(code.stack) >= 2 :
+ s1, s2 = code.stack[-2:]
+ s1type = s1.getType(code.typeMap)
+ s2type = s2.getType(code.typeMap)
+ if s1type != s2type :
+ if s1type in _NUMERIC_TYPES and s2type in _NUMERIC_TYPES :
+ newType = types.FloatType
+ if s1type == ComplexType or s2type == ComplexType:
+ newType = ComplexType
+ newItem.type = newType
+
+ code.popStackItems(2)
+ code.pushStack(newItem)
+
+def _BINARY_ADD(oparg, operand, codeSource, code) :
+ stack = code.stack
+ if len(stack) >= 2 and (stack[-1].const and stack[-2].const and
+ stack[-1].type == stack[-2].type) :
+ value = stack[-2].data + stack[-1].data
+ code.popStackItems(2)
+ code.pushStack(Stack.Item(value, type(value), 1))
+ else :
+ _coerce_type(code)
+
+def _BINARY_SUBTRACT(oparg, operand, codeSource, code) :
+ _coerce_type(code)
+_BINARY_POWER = _BINARY_SUBTRACT
+
+def _BINARY_SUBSCR(oparg, operand, codeSource, code) :
+ _checkNoEffect(code)
+ if len(code.stack) >= 2 :
+ stack = code.stack
+ varType = code.typeMap.get(utils.safestr(stack[-2].data), [])
+ if types.ListType in varType and stack[-1].type == types.TupleType :
+ code.addWarning(msgs.USING_TUPLE_ACCESS_TO_LIST % stack[-2].data)
+ _popStackRef(code, operand)
+
+def _isint(stackItem, code) :
+ if type(stackItem.data) == types.IntType :
+ return 1
+ stackTypes = code.typeMap.get(stackItem.data, [])
+ if len(stackTypes) != 1 :
+ return 0
+ return types.IntType in stackTypes
+
+def _BINARY_DIVIDE(oparg, operand, codeSource, code) :
+ _checkNoEffect(code)
+ _checkModifyNoOp(code, '/', msgs.DIVIDE_VAR_BY_ITSELF, 0)
+ if cfg().intDivide and len(code.stack) >= 2 :
+ if _isint(code.stack[-1], code) and _isint(code.stack[-2], code) :
+ # don't warn if we are going to convert the result to an int
+ if not (len(code.stack) >= 3 and
+ code.stack[-3].data == 'int' and
+ OP.CALL_FUNCTION(code.nextOpInfo()[0])):
+ code.addWarning(msgs.INTEGER_DIVISION % tuple(code.stack[-2:]))
+
+ _popModifiedStack(code, '/')
+
+def _BINARY_TRUE_DIVIDE(oparg, operand, codeSource, code) :
+ _checkNoEffect(code)
+ _checkVariableOperationOnItself(code, operand, msgs.DIVIDE_VAR_BY_ITSELF)
+ _popModifiedStack(code, '/')
+_BINARY_FLOOR_DIVIDE = _BINARY_TRUE_DIVIDE
+
+def _BINARY_MULTIPLY(oparg, operand, codeSource, code) :
+ if len(code.stack) >= 2 :
+ format = _getFormatString(code, codeSource)
+ if format and type(code.stack[-1].data) == types.IntType :
+ code.stack[-2].data = format * code.stack[-1].data
+ code.popStack()
+ else:
+ _coerce_type(code)
+ else:
+ _popModifiedStack(code, '*')
+
+def _BINARY_MODULO(oparg, operand, codeSource, code) :
+ _checkNoEffect(code)
+ if cfg().modulo1 and code.stack and code.stack[-1].data == 1:
+ if len(code.stack) < 2 or \
+ code.stack[-2].getType(code.typeMap) != types.FloatType:
+ code.addWarning(msgs.MODULO_1)
+ _getFormatWarnings(code, codeSource)
+ _popModifiedStack(code, '%')
+ if code.stack:
+ code.stack[-1].const = 0
+
+def _ROT_TWO(oparg, operand, codeSource, code) :
+ if len(code.stack) >= 2 :
+ tmp = code.stack[-2]
+ code.stack[-2] = code.stack[-1]
+ code.stack[-1] = tmp
+
+def _ROT_THREE(oparg, operand, codeSource, code) :
+ """Lifts second and third stack item one position up,
+ moves top down to position three."""
+ if len(code.stack) >= 3 :
+ second = code.stack[-2]
+ third = code.stack[-3]
+ code.stack[-3] = code.stack[-1]
+ code.stack[-2] = third
+ code.stack[-1] = second
+
+def _ROT_FOUR(oparg, operand, codeSource, code) :
+ """Lifts second, third and forth stack item one position up,
+ moves top down to position four."""
+ if len(code.stack) >= 4 :
+ second = code.stack[-2]
+ third = code.stack[-3]
+ fourth = code.stack[-4]
+ code.stack[-4] = code.stack[-1]
+ code.stack[-3] = fourth
+ code.stack[-2] = third
+ code.stack[-1] = second
+
+def _SETUP_EXCEPT(oparg, operand, codeSource, code) :
+ code.has_except = 1
+ code.pushStack(Stack.Item(None, Stack.TYPE_EXCEPT))
+ code.pushStack(Stack.Item(None, Stack.TYPE_EXCEPT))
+
+def _SETUP_FINALLY(oparg, operand, codeSource, code) :
+ if not code.has_except :
+ code.try_finally_first = 1
+
+def _END_FINALLY(oparg, operand, codeSource, code) :
+ if code.try_finally_first and code.index == (len(code.bytes) - 4) :
+ code.starts_and_ends_with_finally = 1
+
+def _LINE_NUM(oparg, operand, codeSource, code) :
+ code.lastLineNum = oparg
+
+def _UNPACK_SEQUENCE(oparg, operand, codeSource, code) :
+ code.unpackCount = oparg
+ if code.stack:
+ top = code.stack[-1]
+ # if we know we have a tuple, make sure we unpack it into the
+ # right # of variables
+ topType = top.getType(code.typeMap)
+ if topType in _SEQUENCE_TYPES:
+ length = top.length
+ # we don't know the length, maybe it's constant and we can find out
+ if length == 0:
+ value = code.constants.get(utils.safestr(top.data))
+ if type(value) in _SEQUENCE_TYPES:
+ length = len(value)
+ if length > 0 and length != oparg:
+ if cfg().unpackLength:
+ code.addWarning(msgs.WRONG_UNPACK_SIZE % (length, oparg))
+ elif topType not in _UNCHECKABLE_STACK_TYPES:
+ if cfg().unpackNonSequence:
+ code.addWarning(msgs.UNPACK_NON_SEQUENCE %
+ (top.data, _getTypeStr(topType)))
+ _modifyStackName(code, '-unpack')
+
+def _SLICE_1_ARG(oparg, operand, codeSource, code) :
+ _popStackRef(code, operand)
+
+_SLICE1 = _SLICE2 = _SLICE_1_ARG
+
+def _SLICE3(oparg, operand, codeSource, code) :
+ _popStackRef(code, operand, 3)
+
+def _check_string_iteration(code, index):
+ try:
+ item = code.stack[index]
+ except IndexError:
+ return
+ if item.getType(code.typeMap) == types.StringType and \
+ cfg().stringIteration:
+ code.addWarning(msgs.STRING_ITERATION % item.data)
+
+def _FOR_LOOP(oparg, operand, codeSource, code) :
+ code.loops = code.loops + 1
+ _check_string_iteration(code, -2)
+ _popStackRef(code, '<for_loop>', 2)
+
+def _GET_ITER(oparg, operand, codeSource, code) :
+ _check_string_iteration(code, -1)
+
+def _FOR_ITER(oparg, operand, codeSource, code) :
+ code.loops = code.loops + 1
+ _popStackRef(code, '<for_iter>', 1)
+
+def _jump(oparg, operand, codeSource, code) :
+ if len(code.stack) > 0 :
+ topOfStack = code.stack[-1]
+ if topOfStack.isMethodCall(codeSource.classObject, cfg().methodArgName):
+ name = topOfStack.data[-1]
+ if codeSource.classObject.methods.has_key(name) :
+ code.addWarning(msgs.USING_METHOD_AS_ATTR % name)
+_JUMP_ABSOLUTE = _jump
+
+def _skip_loops(bytes, i, lastLineNum, max) :
+ extended_arg = 0
+ blockCount = 1
+ while i < max :
+ op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
+ if OP.LINE_NUM(op) :
+ lastLineNum = oparg
+ elif OP.FOR_LOOP(op) or OP.FOR_ITER(op) or OP.SETUP_LOOP(op) :
+ blockCount = blockCount + 1
+ elif OP.POP_BLOCK(op) :
+ blockCount = blockCount - 1
+ if blockCount <= 0 :
+ break
+
+ return lastLineNum, i
+
+def _is_unreachable(code, topOfStack, branch, if_false) :
+ # Are we are checking exceptions, but we not catching all exceptions?
+ if (topOfStack.type == Stack.TYPE_COMPARISON and
+ topOfStack.data[1] == 'exception match' and
+ topOfStack.data[2] is not Exception) :
+ return 1
+
+ # do we possibly have while 1: ?
+ if not (topOfStack.const and topOfStack.data == 1 and if_false) :
+ return 0
+
+ # get the op just before the branch (ie, -3)
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, branch - 3, 0)
+ # are we are jumping to before the while 1: (LOAD_CONST, JUMP_IF_FALSE)
+ if not (OP.JUMP_ABSOLUTE(op) and oparg == (code.index - 3*3)) :
+ return 0
+
+ # check if we break out of the loop
+ i = code.index
+ lastLineNum = code.getLineNum()
+ while i < branch :
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, i, extended_arg)
+ if OP.LINE_NUM(op) :
+ lastLineNum = oparg
+ elif OP.BREAK_LOOP(op) :
+ return 0
+ elif OP.FOR_LOOP(op) or OP.FOR_ITER(op) or OP.SETUP_LOOP(op) :
+ lastLineNum, i = _skip_loops(code.bytes, i, lastLineNum, branch)
+
+ i = code.index - 3*4
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, i, 0)
+ if OP.SETUP_LOOP(op) :
+ # a little lie to pretend we have a raise after a while 1:
+ code.removeBranch(i + oparg)
+ code.raiseValues.append((lastLineNum, None, i + oparg))
+ return 1
+
+# In Python 2.3, while/if 1: gets optimized to
+# ...
+# JUMP_FORWARD 4
+# JUMP_IF_FALSE ?
+# POP_TOP
+#
+# which generates a Using a conditional statement with a constant value
+
+# JUMP_FORWARD = 110; 4, 0 is the offset (4)
+_IGNORE_BOGUS_JUMP = '%c%c%c' % (110, 4, 0)
+def _shouldIgnoreBogusJumps(code):
+ return _shouldIgnoreCodeOptimizations(code, _IGNORE_BOGUS_JUMP, 6, 3)
+
+def _checkConstantCondition(code, topOfStack, if_false):
+ # don't warn when doing (test and 'true' or 'false')
+ # still warn when doing (test and None or 'false')
+ if if_false or not OP.LOAD_CONST(code.nextOpInfo(1)[0]) or \
+ not topOfStack.data or topOfStack.type is types.NoneType:
+ if not _shouldIgnoreBogusJumps(code):
+ code.addWarning(msgs.CONSTANT_CONDITION % utils.safestr(topOfStack))
+
+def _jump_conditional(oparg, operand, codeSource, code, if_false) :
+ # FIXME: this doesn't work in 2.3+ since constant conditions
+ # are optimized away by the compiler.
+ if code.stack :
+ topOfStack = code.stack[-1]
+ if (topOfStack.const or topOfStack.type is types.NoneType) and \
+ cfg().constantConditions and \
+ (topOfStack.data != 1 or cfg().constant1):
+ _checkConstantCondition(code, topOfStack, if_false)
+
+ if _is_unreachable(code, topOfStack, code.label, if_false) :
+ code.removeBranch(code.label)
+
+ _jump(oparg, operand, codeSource, code)
+
+def _JUMP_IF_FALSE(oparg, operand, codeSource, code) :
+ _jump_conditional(oparg, operand, codeSource, code, 1)
+
+def _JUMP_IF_TRUE(oparg, operand, codeSource, code) :
+ _jump_conditional(oparg, operand, codeSource, code, 0)
+
+def _JUMP_FORWARD(oparg, operand, codeSource, code) :
+ _jump(oparg, operand, codeSource, code)
+ code.remove_unreachable_code(code.label)
+
+def _RETURN_VALUE(oparg, operand, codeSource, code) :
+ if not codeSource.calling_code :
+ code.addReturn()
+
+def _EXEC_STMT(oparg, operand, codeSource, code) :
+ if cfg().usesExec :
+ if code.stack and code.stack[-1].isNone() :
+ code.addWarning(msgs.USES_GLOBAL_EXEC)
+ else :
+ code.addWarning(msgs.USES_EXEC)
+
+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:
+ _checkStrException(code, item.getType(code.typeMap), item)
+
+
+DISPATCH = [ None ] * 256
+DISPATCH[ 1] = _POP_TOP
+DISPATCH[ 2] = _ROT_TWO
+DISPATCH[ 3] = _ROT_THREE
+DISPATCH[ 4] = _DUP_TOP
+DISPATCH[ 5] = _ROT_FOUR
+DISPATCH[ 10] = _UNARY_POSITIVE
+DISPATCH[ 11] = _UNARY_NEGATIVE
+DISPATCH[ 12] = _UNARY_NOT
+DISPATCH[ 13] = _UNARY_CONVERT
+DISPATCH[ 15] = _UNARY_INVERT
+DISPATCH[ 18] = _LIST_APPEND
+DISPATCH[ 19] = _BINARY_POWER
+DISPATCH[ 20] = _BINARY_MULTIPLY
+DISPATCH[ 21] = _BINARY_DIVIDE
+DISPATCH[ 22] = _BINARY_MODULO
+DISPATCH[ 23] = _BINARY_ADD
+DISPATCH[ 24] = _BINARY_SUBTRACT
+DISPATCH[ 25] = _BINARY_SUBSCR
+DISPATCH[ 26] = _BINARY_FLOOR_DIVIDE
+DISPATCH[ 27] = _BINARY_TRUE_DIVIDE
+# FIXME: add INPLACE FLOOR/TRUE DIVIDE: 28/29
+DISPATCH[ 31] = _SLICE1
+DISPATCH[ 32] = _SLICE2
+DISPATCH[ 33] = _SLICE3
+DISPATCH[ 55] = _BINARY_ADD # INPLACE
+DISPATCH[ 56] = _BINARY_SUBTRACT # INPLACE
+DISPATCH[ 57] = _BINARY_MULTIPLY # INPLACE
+DISPATCH[ 58] = _BINARY_DIVIDE # INPLACE
+DISPATCH[ 59] = _BINARY_MODULO # INPLACE
+DISPATCH[ 60] = _STORE_SUBSCR
+DISPATCH[ 61] = _DELETE_SUBSCR
+DISPATCH[ 62] = _BINARY_LSHIFT
+DISPATCH[ 63] = _BINARY_RSHIFT
+DISPATCH[ 64] = _BINARY_AND
+DISPATCH[ 65] = _BINARY_XOR
+DISPATCH[ 66] = _BINARY_OR
+DISPATCH[ 67] = _BINARY_POWER # INPLACE
+DISPATCH[ 68] = _GET_ITER
+DISPATCH[ 71] = _PRINT_ITEM
+DISPATCH[ 73] = _PRINT_ITEM_TO
+DISPATCH[ 75] = _BINARY_LSHIFT # INPLACE
+DISPATCH[ 76] = _BINARY_RSHIFT # INPLACE
+DISPATCH[ 77] = _BINARY_AND # INPLACE
+DISPATCH[ 78] = _BINARY_XOR # INPLACE
+DISPATCH[ 79] = _BINARY_OR # INPLACE
+DISPATCH[ 83] = _RETURN_VALUE
+DISPATCH[ 84] = _IMPORT_STAR
+DISPATCH[ 85] = _EXEC_STMT
+DISPATCH[ 88] = _END_FINALLY
+DISPATCH[ 89] = _BUILD_CLASS
+DISPATCH[ 90] = _STORE_NAME
+DISPATCH[ 91] = _DELETE_NAME
+DISPATCH[ 92] = _UNPACK_SEQUENCE
+DISPATCH[ 93] = _FOR_ITER
+DISPATCH[ 95] = _STORE_ATTR
+DISPATCH[ 96] = _DELETE_ATTR
+DISPATCH[ 97] = _STORE_GLOBAL
+DISPATCH[ 98] = _DELETE_GLOBAL
+DISPATCH[100] = _LOAD_CONST
+DISPATCH[101] = _LOAD_NAME
+DISPATCH[102] = _BUILD_TUPLE
+DISPATCH[103] = _BUILD_LIST
+DISPATCH[104] = _BUILD_MAP
+DISPATCH[105] = _LOAD_ATTR
+DISPATCH[106] = _COMPARE_OP
+DISPATCH[107] = _IMPORT_NAME
+DISPATCH[108] = _IMPORT_FROM
+DISPATCH[110] = _JUMP_FORWARD
+DISPATCH[111] = _JUMP_IF_FALSE
+DISPATCH[112] = _JUMP_IF_TRUE
+DISPATCH[113] = _JUMP_ABSOLUTE
+DISPATCH[114] = _FOR_LOOP
+DISPATCH[116] = _LOAD_GLOBAL
+DISPATCH[121] = _SETUP_EXCEPT
+DISPATCH[122] = _SETUP_FINALLY
+DISPATCH[124] = _LOAD_FAST
+DISPATCH[125] = _STORE_FAST
+DISPATCH[126] = _DELETE_FAST
+DISPATCH[127] = _LINE_NUM
+DISPATCH[130] = _RAISE_VARARGS
+DISPATCH[131] = _CALL_FUNCTION
+DISPATCH[132] = _MAKE_FUNCTION
+DISPATCH[134] = _MAKE_CLOSURE
+DISPATCH[135] = _LOAD_CLOSURE
+DISPATCH[136] = _LOAD_DEREF
+DISPATCH[140] = _CALL_FUNCTION_VAR
+DISPATCH[141] = _CALL_FUNCTION_KW
+DISPATCH[142] = _CALL_FUNCTION_VAR_KW