def addMembersFromMethod(self, method) :
        if not hasattr(method, 'func_code') :
            return

        func_code, code, i, maxCode, extended_arg = OP.initFuncCode(method)
        stack = []
        while i < maxCode :
            op, oparg, i, extended_arg = OP.getInfo(code, i, extended_arg)
            if op >= OP.HAVE_ARGUMENT :
                operand = OP.getOperand(op, func_code, oparg)
                if OP.LOAD_CONST(op) or OP.LOAD_FAST(op) or OP.LOAD_GLOBAL(op):
                    stack.append(operand)
                elif OP.LOAD_DEREF(op):
                    try:
                        operand = func_code.co_cellvars[oparg]
                    except IndexError:
                        index = oparg - len(func_code.co_cellvars)
                        operand = func_code.co_freevars[index]
                    stack.append(operand)
                elif OP.STORE_ATTR(op) :
                    if len(stack) > 0 :
                        if stack[-1] == utils.cfg().methodArgName:
                            value = None
                            if len(stack) > 1 :
                                value = type(stack[-2])
                            self.members[operand] = value
                            self.memberRefs[operand] = None
                        stack = []

        self.cleanupMemberRefs()
Ejemplo n.º 2
0
    def addMembersFromMethod(self, method):
        if not hasattr(method, 'func_code'):
            return

        func_code, code, i, maxCode, extended_arg = OP.initFuncCode(method)
        stack = []
        while i < maxCode:
            op, oparg, i, extended_arg = OP.getInfo(code, i, extended_arg)
            if op >= OP.HAVE_ARGUMENT:
                operand = OP.getOperand(op, func_code, oparg)
                if OP.LOAD_CONST(op) or OP.LOAD_FAST(op) or OP.LOAD_GLOBAL(op):
                    stack.append(operand)
                elif OP.LOAD_DEREF(op):
                    try:
                        operand = func_code.co_cellvars[oparg]
                    except IndexError:
                        index = oparg - len(func_code.co_cellvars)
                        operand = func_code.co_freevars[index]
                    stack.append(operand)
                elif OP.STORE_ATTR(op):
                    if len(stack) > 0:
                        if stack[-1] == cfg().methodArgName:
                            value = None
                            if len(stack) > 1:
                                value = type(stack[-2])
                            self.members[operand] = value
                            self.memberRefs[operand] = None
                        stack = []

        self.cleanupMemberRefs()
Ejemplo n.º 3
0
def _findUnreachableCode(code) :
    # code after RETURN or RAISE is unreachable unless there's a branch to it
    unreachable = {}
    terminals = code.returnValues[:-1] + code.raiseValues
    terminals.sort(lambda a, b: cmp(a[2], b[2]))
    for line, dummy, i in terminals :
        if not code.branches.has_key(i) :
            unreachable[i] = line

    # find the index of the last return
    lastLine = lastItem = lastIndex = None
    if code.returnValues:
        lastLine, lastItem, lastIndex = code.returnValues[-1]
    if len(code.returnValues) >= 2 :
        lastIndex = code.returnValues[-2][2]
    if code.raiseValues :
        lastIndex = max(lastIndex, code.raiseValues[-1][2])

    # remove last return if it's unreachable AND implicit
    if unreachable.get(lastIndex) == lastLine and lastItem and \
           lastItem.isImplicitNone():
        del code.returnValues[-1]
        del unreachable[lastIndex]

    if cfg().unreachableCode :
        for index in unreachable.keys() :
            try :
                if not OP.JUMP_FORWARD(ord(code.bytes[index])) :
                    code.addWarning(msgs.CODE_UNREACHABLE, unreachable[index])
            except IndexError :
                pass
Ejemplo n.º 4
0
 def abstractMethod(self, m):
     """Return 1 if method is abstract, None if not
        An abstract method always raises an exception.
     """
     if not self.methods.get(m, None):
         return None
     func_code, bytes, i, maxCode, extended_arg = \
                OP.initFuncCode(self.methods[m].function)
     # abstract if the first conditional is RAISE_VARARGS
     while i < maxCode:
         op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
         if OP.RAISE_VARARGS(op):
             return 1
         if OP.conditional(op):
             break
     return None
Ejemplo n.º 5
0
 def abstractMethod(self, m):
     """Return 1 if method is abstract, None if not
        An abstract method always raises an exception.
     """
     if not self.methods.get(m, None):
         return None
     func_code, bytes, i, maxCode, extended_arg = \
                OP.initFuncCode(self.methods[m].function)
     # abstract if the first conditional is RAISE_VARARGS
     while i < maxCode:
         op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
         if OP.RAISE_VARARGS(op):
             return 1
         if OP.conditional(op):
             break
     return None
Ejemplo n.º 6
0
 def abstractMethod(self, m):
     """Return 1 if method is abstract, None if not
        An abstract method always raises an exception.
     """
     if not self.methods.get(m, None):
         return None
     func_code, bytes, i, maxCode, extended_arg = OP.initFuncCode(self.methods[m].function)
     # abstract if the first opcode is RAISE_VARARGS and it raises
     # NotImplementedError
     arg = ""
     while i < maxCode:
         op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
         if OP.LOAD_GLOBAL(op):
             arg = func_code.co_names[oparg]
         elif OP.RAISE_VARARGS(op):
             # if we saw NotImplementedError sometime before the raise
             # assume it's related to this raise stmt
             return arg == "NotImplementedError"
         if OP.conditional(op):
             break
     return None
Ejemplo n.º 7
0
 def abstractMethod(self, m):
     """Return 1 if method is abstract, None if not
        An abstract method always raises an exception.
     """
     if not self.methods.get(m, None):
         return None
     func_code, bytes, i, maxCode, extended_arg = \
                OP.initFuncCode(self.methods[m].function)
     # abstract if the first opcode is RAISE_VARARGS and it raises
     # NotImplementedError
     arg = ""
     while i < maxCode:
         op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
         if OP.LOAD_GLOBAL(op):
             arg = func_code.co_names[oparg]
         elif OP.RAISE_VARARGS(op):
             # if we saw NotImplementedError sometime before the raise
             # assume it's related to this raise stmt
             return arg == "NotImplementedError"
         if OP.conditional(op):
             break
     return None
Ejemplo n.º 8
0
    def addMembersFromMethod(self, method) :
        if not hasattr(method, 'func_code') :
            return

        func_code, code, i, maxCode, extended_arg = OP.initFuncCode(method)
        stack = []
        while i < maxCode :
            op, oparg, i, extended_arg = OP.getInfo(code, i, extended_arg)
            if op >= OP.HAVE_ARGUMENT :
                operand = OP.getOperand(op, func_code, oparg)
                if OP.LOAD_CONST(op) or OP.LOAD_FAST(op) :
                    stack.append(operand)
                elif OP.STORE_ATTR(op) :
                    if len(stack) > 0 :
                        if stack[-1] == cfg().methodArgName:
                            value = None
                            if len(stack) > 1 :
                                value = type(stack[-2])
                            self.members[operand] = value
                            self.memberRefs[operand] = None
                        stack = []

        self.cleanupMemberRefs()
Ejemplo n.º 9
0
def _checkFunction(module, func, c = None, main = 0, in_class = 0) :
    """
    Return a list of Warnings found in a function/method.

    @type  module: L{pychecker.checker.PyCheckerModule}
    """

    # always push a new config object, so we can pop at end of function
    utils.pushConfig()

    code = CodeChecks.Code()
    code.init(func)
    if main:
        for key in func.function.func_globals.keys():
            code.unusedLocals[key] = -1
    codeSource = CodeChecks.CodeSource(module, func, c, main, in_class, code)
    try :
        _checkCode(code, codeSource)
        if not in_class :
            _findUnreachableCode(code)

        # handle lambdas and nested functions
        codeSource.calling_code.append(func)
        for key in code.codeOrder:
            func_code = code.codeObjects[key]
            _handleNestedCode(func_code, code, codeSource)
        del codeSource.calling_code[-1]

    except (SystemExit, KeyboardInterrupt) :
        exc_type, exc_value, exc_tb = sys.exc_info()
        raise exc_type, exc_value
    except :
        exc_type, exc_value, exc_tb = sys.exc_info()
        exc_list = traceback.format_exception(exc_type, exc_value, exc_tb)
        for index in range(0, len(exc_list)) :
            exc_list[index] = string.replace(exc_list[index], "\n", "\n\t")
        code.addWarning(msgs.CHECKER_BROKEN % string.join(exc_list, ""))

    if cfg().checkReturnValues :
        _checkReturnWarnings(code)

    if cfg().localVariablesUsed :
        for var, line in code.unusedLocals.items() :
            if line is not None and line > 0 and _name_unused(var) :
                code.addWarning(msgs.UNUSED_LOCAL % var, line)

    if cfg().argumentsUsed :
        op = code.getFirstOp()
        if not (OP.RAISE_VARARGS(op) or OP.RETURN_VALUE(op)) :
            for var, line in code.unusedLocals.items() :
                _checkUnusedParam(var, line, func, code)

    # Check code complexity:
    #   loops should be counted as one branch, but there are typically 3
    #   branches in byte code to setup a loop, so subtract off 2/3's of them
    #    / 2 to approximate real branches
    branches = (len(code.branches.keys()) - (2 * code.loops)) / 2
    lines = (code.getLineNum() - code.func_code.co_firstlineno)
    returns = len(code.returnValues)
    if not main and not in_class :
        args = code.func_code.co_argcount
        localCount = len(code.func_code.co_varnames) - args
        _checkComplex(code, cfg().maxArgs, args, func, msgs.TOO_MANY_ARGS)
        _checkComplex(code, cfg().maxLocals, localCount, func,
            msgs.TOO_MANY_LOCALS)
        _checkComplex(code, cfg().maxLines, lines, func, msgs.FUNC_TOO_LONG)
    _checkComplex(code, cfg().maxReturns, returns, func, msgs.TOO_MANY_RETURNS)
    _checkComplex(code, cfg().maxBranches, branches, func,
        msgs.TOO_MANY_BRANCHES)

    if not (main or in_class) :
        utils.popConfig()
    func.returnValues = code.returnValues
    # FIXME: I don't think code.codeObjects.values() ever gets used,
    # but if it does, and needs to be in order, then use code.codeOrder here.
    return (code.warnings, code.globalRefs, code.functionsCalled,
            code.codeObjects.values(), code.returnValues)