Tuesday, February 8, 2011

Function return types are inconsistent messages in PyChecker

PyChecker returns a whole slew of warning/error messages, including "Function return types are inconsistent". What does this message mean? Well essentially behind the scenes what PyChecker attempts to do is create an array list of all the return values/types in your function inside the code.returnValues variable. If there are at least 2 sets of return values, then PyChecker can iterate through by picking the first return value pair and comparing it against the rest. If there is a mismatch, the INCONSISTENT_RETURN_TYPE flag is raised.

The following code in pychecker/warn.py does the checking:

def _checkReturnWarnings(code) :
    is_getattr = code.func_code.co_name in ('__getattr__', '__getattribute__')
    if is_getattr :
        for line, retval, dummy in code.returnValues :
            if retval.isNone() :
                err = msgs.DONT_RETURN_NONE % code.func_code.co_name
                code.addWarning(err, line+1)

    # there must be at least 2 real return values to check for consistency                                                                        
    returnValuesLen = len(code.returnValues)

    for line, value, dummy in code.returnValues :
        if not value.isNone() :
            valueType = value.getType(code.typeMap)
            if returnType is None and valueType not in _IGNORE_RETURN_TYPES :
                returnData = value
                returnType = valueType

            # always ignore None, None can be returned w/any other type                                                                           
            # FIXME: if we stored func return values, we could do better                                                                          
            if returnType is not None and not value.isNone() and \
               valueType not in _IGNORE_RETURN_TYPES and \
               returnData.type not in _IGNORE_RETURN_TYPES :
                ok = returnType in (type(value.data), valueType)
                if ok :
                    if returnType == types.TupleType :
                        # FIXME: this isn't perfect, if len == 0                                                                                  
                        # the length can really be 0 OR unknown                                                                                   
                        # we shouldn't check the lengths for equality                                                                             
                        # ONLY IF one of the lengths is truly unknown                                                                             
                        if returnData.length > 0 and value.length > 0:
                            ok = returnData.length == value.length
                else :
                    ok = _checkSubclass(returnType, valueType) or \
                         _checkSubclass(valueType, returnType)
                if not ok :
                    code.addWarning(msgs.INCONSISTENT_RETURN_TYPE, line)

No comments:

Post a Comment