Example #1
0
    def testGenerator(self):
        def returner():
            return (str(x) for x in range(10))

        # get the generator code object
        genCode = returner.func_code.co_consts[1]

        # FIXME: this is what co_varnames looks like, but I don't understand why
        # possible clue in Python, Lib/compiler/ast.py, class GenExpr
        if utils.pythonVersion() < utils.PYTHON_2_5:
            self.assertEquals(genCode.co_varnames, ('[outmost-iterable]', 'x'))
        else:
            self.assertEquals(genCode.co_varnames, ('.0', 'x'))

        # wrap it into a Funtion so we can look at it
        f = function.Function(
            function.FakeFunction(genCode.co_name, genCode))

        self.failIf(f.isMethod)
        self.assertEquals(f.minArgs, 1)
        self.assertEquals(f.maxArgs, 1)
        if utils.pythonVersion() < utils.PYTHON_2_5:
            self.assertEquals(f.arguments(), ('[outmost-iterable]', ))
        else:
            self.assertEquals(f.arguments(), ('.0', ))
Example #2
0
    def test_star_import(self):
        warnings = self.check(['input/starimport.py', ])

        self.assertEquals(len(warnings), 0, self.formatWarnings(warnings))

        # check the module doing the star import
        pcmodule = pcmodules.getPCModule("starimport", moduleDir="input")
        self.assertEquals(pcmodule.moduleName, "starimport")
        self.assertEquals(pcmodule.moduleDir, "input")

        if utils.pythonVersion() >= utils.PYTHON_2_6:
            self.assertEquals(pcmodule.variables.keys(), ["__package__"])
        else:
            self.assertEquals(pcmodule.variables.keys(), [])
        self.assertEquals(pcmodule.classes.keys(), [])
        self.assertEquals(pcmodule.functions.keys(), [])
        self.assertEquals(pcmodule.modules.keys(), ["gettext", ])

        # check the code
        self.assertEquals(len(pcmodule.codes), 1)
        self.assertEquals(pcmodule.codes[0].func.function.func_name, '__main__')

        # FIXME: why do we have a non-empty stack here ?
        # self.assertEquals(pcmodule.codes[0].stack, [])

        modules = pcmodules._getPCModulesDict()
        for (name, moduleDir) in modules.keys():
            self.failIf(name.find('*') > -1,
                'Invalid loaded module name %s' % (name, ))

        # check the module from which we are starimporting;
        # it should have been loaded as a side effect
        pcmodule = pcmodules.getPCModule("starimportfrom", moduleDir="input")
        self.failUnless(pcmodule, pcmodules._getPCModulesDict())
        self.assertEquals(pcmodule.moduleName, "starimportfrom")
        self.assertEquals(pcmodule.moduleDir, "input")

        variables = [v for v in pcmodule.variables.keys()
            if v not in Config._DEFAULT_VARIABLE_IGNORE_LIST]
        if utils.pythonVersion() >= utils.PYTHON_2_6:
            self.assertEquals(pcmodule.variables.keys(), ["__package__"])
        else:
            self.assertEquals(pcmodule.variables.keys(), [])
        self.assertEquals(pcmodule.classes.keys(), [])
        self.assertEquals(pcmodule.functions.keys(), ["_", ])
        self.assertEquals(pcmodule.modules.keys(), ["gettext", ])

        # check the code
        self.assertEquals(len(pcmodule.codes), 0)
Example #3
0
    def test_nested(self):
        warnings = self.check(['input/nested.py', ])

        self.assertEquals(len(warnings), 1, self.formatWarnings(warnings))
        self.assertWarnings(warnings, ['input/nested.py'])

        # check the module and the code
        pcmodule = pcmodules.getPCModule("nested", moduleDir="input")
        self.assertEquals(pcmodule.moduleName, "nested")
        self.assertEquals(pcmodule.moduleDir, "input")

        if utils.pythonVersion() >= utils.PYTHON_2_6:
            self.assertEquals(pcmodule.variables.keys(), ["__package__"])
        else:
            self.assertEquals(pcmodule.variables.keys(), [])
        self.assertEquals(pcmodule.classes.keys(), ["Result"])
        self.assertEquals(pcmodule.functions.keys(), ["outside"])

        # check the code
        self.assertEquals(len(pcmodule.codes), 4)
        self.assertEquals(pcmodule.codes[0].func.function.func_name, '__main__')
        # FIXME: this assert is wrong; the code should be named outside,
        # but since the code object got re-used for nested code, it's called
        # second
        self.assertEquals(pcmodule.codes[1].func.function.func_name, 'outside')
        self.assertEquals(pcmodule.codes[2].func.function.func_name, 'Result')
        self.assertEquals(pcmodule.codes[3].func.function.func_name, '__init__')

        self.failIf(pcmodule.codes[0].stack)
        # FIXME: why do we have a non-empty stack here ?
        # self.failIf(pcmodule.codes[1].stack, pcmodule.codes[1].stack)
        self.failIf(pcmodule.codes[2].stack)
        self.failIf(pcmodule.codes[3].stack)
Example #4
0
    def test_star_import_from(self):
        # First make sure that gettext only exists as a module, not as
        # a function
        warnings = self.check(['input/starimportfrom.py', ])

        self.assertEquals(len(warnings), 0, self.formatWarnings(warnings))

        pcmodule = pcmodules.getPCModule("starimportfrom", moduleDir="input")
        self.assertEquals(pcmodule.moduleName, "starimportfrom")
        self.assertEquals(pcmodule.moduleDir, "input")

        variables = [v for v in pcmodule.variables.keys()
            if v not in Config._DEFAULT_VARIABLE_IGNORE_LIST]
        if utils.pythonVersion() >= utils.PYTHON_2_6:
            self.assertEquals(variables, ["__package__"])
        else:
            self.assertEquals(variables, [])
        self.assertEquals(pcmodule.classes.keys(), [])
        self.assertEquals(pcmodule.functions.keys(), ['_'])
        self.assertEquals(pcmodule.modules.keys(), ["gettext", ])

        # check the code
        self.assertEquals(len(pcmodule.codes), 2,
            [c.func.function.func_name for c in pcmodule.codes])
        self.assertEquals(pcmodule.codes[0].func.function.func_name, '__main__')
        self.assertEquals(pcmodule.codes[1].func.function.func_name, 'gettext')

        # FIXME: why do we have a non-empty stack here ?
        # self.assertEquals(pcmodule.codes[0].stack, [])
        self.assertEquals(pcmodule.codes[1].stack, [])
Example #5
0
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)
    if returnValuesLen < 2 :
        return

    # if the last return is implicit, check if there are non None returns
    lastReturn = code.returnValues[-1]

    # Python 2.4 optimizes the dead implicit return out, so we can't
    # distinguish implicit and explicit "return None"
    if utils.pythonVersion() < utils.PYTHON_2_4 and \
           not code.starts_and_ends_with_finally and \
           cfg().checkImplicitReturns and lastReturn[1].isImplicitNone():
        for line, retval, dummy in code.returnValues[:-1] :
            if not retval.isNone() :
                code.addWarning(msgs.IMPLICIT_AND_EXPLICIT_RETURNS,
                                lastReturn[0]+1)
                break

    # __get*__ funcs can return different types, don't warn about inconsistency
    if utils.startswith(code.func_code.co_name, '__get') and \
       utils.endswith(code.func_code.co_name, '__') :
        return

    returnType, returnData = None, None
    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
                continue

            # 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)
Example #6
0
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)
    if returnValuesLen < 2 :
        return

    # if the last return is implicit, check if there are non None returns
    lastReturn = code.returnValues[-1]

    # Python 2.4 optimizes the dead implicit return out, so we can't
    # distinguish implicit and explicit "return None"
    if utils.pythonVersion() < utils.PYTHON_2_4 and \
           not code.starts_and_ends_with_finally and \
           cfg().checkImplicitReturns and lastReturn[1].isImplicitNone():
        for line, retval, dummy in code.returnValues[:-1] :
            if not retval.isNone() :
                code.addWarning(msgs.IMPLICIT_AND_EXPLICIT_RETURNS,
                                lastReturn[0]+1)
                break

    # __get*__ funcs can return different types, don't warn about inconsistency
    if utils.startswith(code.func_code.co_name, '__get') and \
       utils.endswith(code.func_code.co_name, '__') :
        return

    returnType, returnData = None, None
    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
                continue

            # 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)
Example #7
0
def _setupBuiltinAttrs():
    item = Stack.Item(None, None)
    BUILTIN_ATTRS[types.MethodType] = dir(item.__init__)
    del item

    if utils.pythonVersion() >= utils.PYTHON_2_2:
        # FIXME: I'm sure more types need to be added here
        BUILTIN_ATTRS[types.StringType] = dir("".__class__)
        BUILTIN_ATTRS[types.ListType] = dir([].__class__)
        BUILTIN_ATTRS[types.DictType] = dir({}.__class__)

    try:
        import warnings

        _MSG = "xrange object's 'start', 'stop' and 'step' attributes are deprecated"
        warnings.filterwarnings("ignore", _MSG)
        del warnings, _MSG
    except (ImportError, AssertionError):
        pass
    BUILTIN_ATTRS[types.XRangeType] = dir(xrange(0))

    try:
        BUILTIN_ATTRS[types.ComplexType] = dir(complex(0, 1))
    except:
        pass

    try:
        BUILTIN_ATTRS[types.UnicodeType] = dir(unicode(""))
    except:
        pass

    try:
        BUILTIN_ATTRS[types.CodeType] = dir(_setupBuiltinAttrs.func_code)
    except:
        pass

    try:
        BUILTIN_ATTRS[types.FileType] = dir(sys.__stdin__)
    except:
        pass

    try:
        raise TypeError
    except TypeError:
        try:
            tb = sys.exc_info()[2]
            BUILTIN_ATTRS[types.TracebackType] = dir(tb)
            BUILTIN_ATTRS[types.FrameType] = dir(tb.tb_frame)
        except:
            pass
        tb = None
Example #8
0
def _setupBuiltinAttrs():
    item = Stack.Item(None, None)
    BUILTIN_ATTRS[types.MethodType] = dir(item.__init__)
    del item

    if utils.pythonVersion() >= utils.PYTHON_2_2:
        # FIXME: I'm sure more types need to be added here
        BUILTIN_ATTRS[types.StringType] = dir(''.__class__)
        BUILTIN_ATTRS[types.ListType] = dir([].__class__)
        BUILTIN_ATTRS[types.DictType] = dir({}.__class__)

    try:
        import warnings
        _MSG = "xrange object's 'start', 'stop' and 'step' attributes are deprecated"
        warnings.filterwarnings('ignore', _MSG)
        del warnings, _MSG
    except (ImportError, AssertionError):
        pass
    BUILTIN_ATTRS[types.XRangeType] = dir(xrange(0))

    try:
        BUILTIN_ATTRS[types.ComplexType] = dir(complex(0, 1))
    except:
        pass

    try:
        BUILTIN_ATTRS[types.UnicodeType] = dir(unicode(''))
    except:
        pass

    try:
        BUILTIN_ATTRS[types.CodeType] = dir(_setupBuiltinAttrs.func_code)
    except:
        pass

    try:
        BUILTIN_ATTRS[types.FileType] = dir(sys.__stdin__)
    except:
        pass

    try:
        raise TypeError
    except TypeError:
        try:
            tb = sys.exc_info()[2]
            BUILTIN_ATTRS[types.TracebackType] = dir(tb)
            BUILTIN_ATTRS[types.FrameType] = dir(tb.tb_frame)
        except:
            pass
        tb = None
Example #9
0
    def test_unused_import(self):
        warnings = self.check(['input/unused_import.py', ])

        self.assertEquals(len(warnings), 4, self.formatWarnings(warnings))
        self.assertWarnings(warnings, ['input/unused_import.py'])

        # check the module and the code
        pcmodule = pcmodules.getPCModule("unused_import", moduleDir="input")
        self.assertEquals(pcmodule.moduleName, "unused_import")
        self.assertEquals(pcmodule.moduleDir, "input")

        if utils.pythonVersion() >= utils.PYTHON_2_6:
            self.assertEquals(pcmodule.variables.keys(), ["__package__"])
        else:
            self.assertEquals(pcmodule.variables.keys(), [])
        self.assertEquals(pcmodule.classes, {})
        self.assertEquals(pcmodule.functions.keys(), ["do"])

        # check the code
        self.assertEquals(len(pcmodule.codes), 2)
        main = pcmodule.codes[0]

        # all triggered warnings were import warnings
        self.failIf(main.warnings)

        # FIXME: should the stack not be empty after processing it all ?
        # self.failIf(main.stack)

        modules = pcmodule.modules.keys()
        modules.sort()
        self.assertEquals(modules, ["dom", "path", "sax", "sys"])
        self.assertEquals(pcmodule.moduleLineNums,
            {
                'dom':                  ('input/unused_import.py', 10),
                'do':                   ('input/unused_import.py', 12),
                'sys':                  ('input/unused_import.py', 4),
                'path':                 ('input/unused_import.py', 6),
                ('os', 'path'):         ('input/unused_import.py', 6),
                ('os',):                ('input/unused_import.py', 6),
                'sax':                  ('input/unused_import.py', 8),
                'xml.sax':              ('input/unused_import.py', 8),
                ('xml', ):              ('input/unused_import.py', 10),
                ('xml', 'dom'):         ('input/unused_import.py', 10),
            })
Example #10
0
def _setupBuiltinMethods() :
    if utils.pythonVersion() >= utils.PYTHON_2_2 :
        PY22_DICT_METHODS = { 'iteritems': (types.ListType, 0, 0),
                              'iterkeys': (types.ListType, 0, 0),
                              'itervalues': (types.ListType, 0, 0),
                            }

        BUILTIN_METHODS[types.DictType].update(PY22_DICT_METHODS)

    try :
        BUILTIN_METHODS[types.ComplexType] = \
                                  { 'conjugate': (types.ComplexType, 0, 0), }
    except AttributeError :
        pass

    if len(dir('')) > 0 :
        BUILTIN_METHODS[types.StringType] = _STRING_METHODS

    try :
        BUILTIN_METHODS[types.UnicodeType] = _STRING_METHODS
    except AttributeError :
        pass
Example #11
0
def _setupBuiltinMethods() :
    if utils.pythonVersion() >= utils.PYTHON_2_2 :
        PY22_DICT_METHODS = { 'iteritems': (types.ListType, 0, 0),
                              'iterkeys': (types.ListType, 0, 0),
                              'itervalues': (types.ListType, 0, 0),
                            }

        BUILTIN_METHODS[types.DictType].update(PY22_DICT_METHODS)

    try :
        BUILTIN_METHODS[types.ComplexType] = \
                                  { 'conjugate': (types.ComplexType, 0, 0), }
    except AttributeError :
        pass

    if len(dir('')) > 0 :
        BUILTIN_METHODS[types.StringType] = _STRING_METHODS

    try :
        BUILTIN_METHODS[types.UnicodeType] = _STRING_METHODS
    except AttributeError :
        pass
Example #12
0
    'round': (types.FloatType, 1, 2),
    'setattr': (types.NoneType, 3, 3),
    'slice': (types.SliceType, 1, 3),
    'str': (types.StringType, 1, 1),
    'tuple': (types.TupleType, 1, 1),
    'type': (types.TypeType, 1, 1),
    'vars': (types.DictType, 0, 1),
    'xrange': (types.ListType, 1, 3),
}

if hasattr(types, 'UnicodeType'):
    GLOBAL_FUNC_INFO['unichr'] = (types.UnicodeType, 1, 1)
    GLOBAL_FUNC_INFO['unicode'] = (types.UnicodeType, 1, 3,
                                   ['string', 'encoding', 'errors'])

if utils.pythonVersion() >= utils.PYTHON_2_2:
    GLOBAL_FUNC_INFO['compile'] = (types.CodeType, 3, 5)
    GLOBAL_FUNC_INFO['dict'] = (types.DictType, 0, 1, ['items'])
    GLOBAL_FUNC_INFO['file'] = GLOBAL_FUNC_INFO['open']
    GLOBAL_FUNC_INFO['float'] = (types.FloatType, 0, 1, ['x'])
    GLOBAL_FUNC_INFO['int'] = (types.IntType, 0, 2, ['x'])
    GLOBAL_FUNC_INFO['list'] = (types.ListType, 0, 1, ['sequence'])
    GLOBAL_FUNC_INFO['long'] = (types.LongType, 0, 2, ['x'])
    GLOBAL_FUNC_INFO['str'] = (types.StringType, 0, 1, ['object'])
    # FIXME: type doesn't take 2 args, only 1 or 3
    GLOBAL_FUNC_INFO['type'] = (types.TypeType, 1, 3,
                                ['name', 'bases', 'dict'])
    GLOBAL_FUNC_INFO['tuple'] = (types.TupleType, 0, 1, ['sequence'])

    GLOBAL_FUNC_INFO['classmethod'] = (types.MethodType, 1, 1)
    GLOBAL_FUNC_INFO['iter'] = (Stack.TYPE_UNKNOWN, 1, 2)
Example #13
0
                     'repr': (types.StringType, 1, 1),
                     'round': (types.FloatType, 1, 2),
                     'setattr': (types.NoneType, 3, 3),
                     'slice': (types.SliceType, 1, 3),
                     'str': (types.StringType, 1, 1),
                     'tuple': (types.TupleType, 1, 1),
                     'type': (types.TypeType, 1, 1),
                     'vars': (types.DictType, 0, 1),
                     'xrange': (types.ListType, 1, 3),
                   }

if hasattr(types, 'UnicodeType') :
    GLOBAL_FUNC_INFO['unichr'] = (types.UnicodeType, 1, 1)
    GLOBAL_FUNC_INFO['unicode'] = (types.UnicodeType, 1, 3, ['string', 'encoding', 'errors'])

if utils.pythonVersion() >= utils.PYTHON_2_2 :
    GLOBAL_FUNC_INFO['compile'] = (types.CodeType, 3, 5)
    GLOBAL_FUNC_INFO['dict'] = (types.DictType, 0, 1, ['items'])
    GLOBAL_FUNC_INFO['file'] = GLOBAL_FUNC_INFO['open']
    GLOBAL_FUNC_INFO['float'] = (types.FloatType, 0, 1, ['x'])
    GLOBAL_FUNC_INFO['int'] = (types.IntType, 0, 2, ['x'])
    GLOBAL_FUNC_INFO['list'] = (types.ListType, 0, 1, ['sequence'])
    GLOBAL_FUNC_INFO['long'] = (types.LongType, 0, 2, ['x'])
    GLOBAL_FUNC_INFO['str'] = (types.StringType, 0, 1, ['object'])
    # FIXME: type doesn't take 2 args, only 1 or 3
    GLOBAL_FUNC_INFO['type'] = (types.TypeType, 1, 3, ['name', 'bases', 'dict'])
    GLOBAL_FUNC_INFO['tuple'] = (types.TupleType, 0, 1, ['sequence'])

    GLOBAL_FUNC_INFO['classmethod'] = (types.MethodType, 1, 1)
    GLOBAL_FUNC_INFO['iter'] = (Stack.TYPE_UNKNOWN, 1, 2)
    GLOBAL_FUNC_INFO['property'] = (Stack.TYPE_UNKNOWN, 0, 4, ['fget', 'fset', 'fdel', 'doc'])
Example #14
0
    return op == 127


def LOAD_GLOBAL(op):
    return op == 116


def LOAD_CONST(op):
    return op == 100


def LOAD_FAST(op):
    return op == 124


if utils.pythonVersion() >= utils.PYTHON_2_7:

    def LOAD_ATTR(op):
        return op == 106
else:

    def LOAD_ATTR(op):
        return op == 105


def LOAD_DEREF(op):
    return op == 136


def STORE_ATTR(op):
    return op == 95
Example #15
0
# Portions Copyright (c) 2005, Google, Inc.  All rights reserved.

"""
Python byte code operations.

Very similar to the dis and opcode module, but dis does not exist in Jython,
so recreate the small portion we need here.
"""

from pychecker import utils

def LINE_NUM(op):              return op == 127
def LOAD_GLOBAL(op):           return op == 116
def LOAD_CONST(op):            return op == 100
def LOAD_FAST(op):             return op == 124
if utils.pythonVersion() >= utils.PYTHON_2_7:
    def LOAD_ATTR(op):             return op == 106
else:
    def LOAD_ATTR(op):             return op == 105
def LOAD_DEREF(op):            return op == 136
def STORE_ATTR(op):            return op == 95
def POP_TOP(op):               return op == 1
if utils.pythonVersion() >= utils.PYTHON_2_7:
    def IMPORT_FROM(op):           return op == 109
else:
    def IMPORT_FROM(op):           return op == 108
def IMPORT_STAR(op):           return op == 84
def UNARY_POSITIVE(op):        return op == 10
def UNARY_NEGATIVE(op):        return op == 11
def UNARY_INVERT(op):          return op == 15
def RETURN_VALUE(op):          return op == 83