Exemplo n.º 1
0
 def getName(self):
     if self.type == TYPE_ATTRIBUTE and type(self.data) != types.StringType:
         strValue = ""
         # convert the tuple into a string ('self', 'data') -> self.data
         for item in self.data:
             strValue = '%s.%s' % (strValue, utils.safestr(item))
         return strValue[1:]
     return utils.safestr(self.data)
Exemplo n.º 2
0
 def getName(self) :
     if self.type == TYPE_ATTRIBUTE and type(self.data) != types.StringType:
         strValue = ""
         # convert the tuple into a string ('self', 'data') -> self.data
         for item in self.data :
             strValue = '%s.%s' % (strValue, utils.safestr(item))
         return strValue[1:]
     return utils.safestr(self.data)
Exemplo n.º 3
0
 def __str__(self) :
     if type(self.data) == types.TupleType :
         value = '('
         for item in self.data :
             value = value + utils.safestr(item) + ', '
         # strip off the ', ' for multiple items
         if len(self.data) > 1 :
             value = value[:-2]
         return value + ')'
     return utils.safestr(self.data)
Exemplo n.º 4
0
 def getName(self):
     # if the item is an attribute but not a string, it's a tuple
     # of object indirections
     if self.type == TYPE_ATTRIBUTE and type(self.data) != types.StringType:
         strValue = ""
         # convert the tuple into a string ('self', 'data') -> self.data
         for item in self.data:
             strValue = '%s.%s' % (strValue, utils.safestr(item))
         return strValue[1:]
     return utils.safestr(self.data)
Exemplo n.º 5
0
 def getName(self):
     # if the item is an attribute but not a string, it's a tuple
     # of object indirections
     if self.type == TYPE_ATTRIBUTE and type(self.data) != types.StringType:
         strValue = ""
         # convert the tuple into a string ('self', 'data') -> self.data
         for item in self.data:
             strValue = "%s.%s" % (strValue, utils.safestr(item))
         return strValue[1:]
     return utils.safestr(self.data)
Exemplo n.º 6
0
 def __str__(self):
     if type(self.data) == types.TupleType:
         value = '('
         for item in self.data:
             value = value + utils.safestr(item) + ', '
         # strip off the ', ' for multiple items
         if len(self.data) > 1:
             value = value[:-2]
         return value + ')'
     return utils.safestr(self.data)
Exemplo n.º 7
0
def importError(moduleName, moduleDir=None):
    exc_type, exc_value, tb = sys.exc_info()

    # First, try to get a nice-looking name for this exception type.
    exc_name = getattr(exc_type, '__name__', None)
    if not exc_name:
        # either it's a string exception or a user-defined exception class
        # show string or fully-qualified class name
        exc_name = utils.safestr(exc_type)
        
    # Print a traceback, unless this is an ImportError.  ImportError is
    # presumably the most common import-time exception, so this saves
    # the clutter of a traceback most of the time.  Also, the locus of
    # the error is usually irrelevant for ImportError, so the lack of
    # traceback shouldn't be a problem.
    if exc_type is SyntaxError:
        # SyntaxErrors are special, we want to control how we format
        # the output and make it consistent for all versions of Python
        e = exc_value
        msg = '%s (%s, line %d)' % (e.msg, e.filename, e.lineno)
        line = _getLineInFile(moduleName, moduleDir, e.lineno)
        offset = e.offset
        if type(offset) is not types.IntType:
            offset = 0
        exc_value = '%s\n    %s\n   %s^' % (msg, line, ' ' * offset)
    elif exc_type is not ImportError:
        sys.stderr.write("  Caught exception importing module %s:\n" %
                         moduleName)

        try:
            tbinfo = traceback.extract_tb(tb)
        except:
            tbinfo = []
            sys.stderr.write("      Unable to format traceback\n")
        for filename, line, func, text in tbinfo[1:]:
            sys.stderr.write("    File \"%s\", line %d" % (filename, line))
            if func != "?":
                sys.stderr.write(", in %s()" % func)
            sys.stderr.write("\n")
            if text:
                sys.stderr.write("      %s\n" % text)

    # And finally print the exception type and value.
    # Careful formatting exc_value -- can fail for some user exceptions
    sys.stderr.write("  %s: " % exc_name)
    try:
        sys.stderr.write(utils.safestr(exc_value) + '\n')
    except:
        sys.stderr.write('**error formatting exception value**\n')
Exemplo n.º 8
0
def importError(moduleName, moduleDir=None):
    exc_type, exc_value, tb = sys.exc_info()

    # First, try to get a nice-looking name for this exception type.
    exc_name = getattr(exc_type, '__name__', None)
    if not exc_name:
        # either it's a string exception or a user-defined exception class
        # show string or fully-qualified class name
        exc_name = utils.safestr(exc_type)

    # Print a traceback, unless this is an ImportError.  ImportError is
    # presumably the most common import-time exception, so this saves
    # the clutter of a traceback most of the time.  Also, the locus of
    # the error is usually irrelevant for ImportError, so the lack of
    # traceback shouldn't be a problem.
    if exc_type is SyntaxError:
        # SyntaxErrors are special, we want to control how we format
        # the output and make it consistent for all versions of Python
        e = exc_value
        msg = '%s (%s, line %d)' % (e.msg, e.filename, e.lineno)
        line = _getLineInFile(moduleName, moduleDir, e.lineno)
        offset = e.offset
        if type(offset) is not types.IntType:
            offset = 0
        exc_value = '%s\n    %s\n   %s^' % (msg, line, ' ' * offset)
    elif exc_type is not ImportError:
        sys.stderr.write("  Caught exception importing module %s:\n" %
                         moduleName)

        try:
            tbinfo = traceback.extract_tb(tb)
        except:
            tbinfo = []
            sys.stderr.write("      Unable to format traceback\n")
        for filename, line, func, text in tbinfo[1:]:
            sys.stderr.write("    File \"%s\", line %d" % (filename, line))
            if func != "?":
                sys.stderr.write(", in %s()" % func)
            sys.stderr.write("\n")
            if text:
                sys.stderr.write("      %s\n" % text)

    # And finally print the exception type and value.
    # Careful formatting exc_value -- can fail for some user exceptions
    sys.stderr.write("  %s: " % exc_name)
    try:
        sys.stderr.write(utils.safestr(exc_value) + '\n')
    except:
        sys.stderr.write('**error formatting exception value**\n')
Exemplo n.º 9
0
def _checkBaseClassInit(moduleFilename, c, func_code, funcInfo) :
    """
    Return a list of warnings that occur for each base class whose __init__()
    is not called

    @param funcInfo: triple of functions called, code objects, return values
    @type  funcInfo: triple
    """

    warnings = []
    functionsCalled, _, returnValues = funcInfo
    for line, stackItem, dummy in returnValues :
        if stackItem.data != None :
            if not stackItem.isNone() or cfg().returnNoneFromInit :
                warn = Warning(func_code, line, msgs.RETURN_FROM_INIT)
                warnings.append(warn)

    classInit = getattr(c.classObject, utils.INIT, None)
    if cfg().baseClassInitted and classInit is not None :
        classInitInfo = _get_func_info(classInit)
        for base in getattr(c.classObject, '__bases__', None) or ():
            if not _baseInitCalled(classInitInfo, base, functionsCalled):
                warn = Warning(moduleFilename, func_code,
                               msgs.BASE_CLASS_NOT_INIT % utils.safestr(base))
                warnings.append(warn)
    return warnings
Exemplo n.º 10
0
    def __import__(name, globals=None, locals=None, fromlist=None):
        if globals is None:
            globals = {}
        if locals is None:
            locals = {}
        if fromlist is None:
            fromlist = []

        check = not sys.modules.has_key(name) and name[:10] != 'pychecker.'
        pymodule = _orig__import__(name, globals, locals, fromlist)
        if check :
            try :
                # FIXME: can we find a good moduleDir ?
                module = PyCheckerModule(pymodule.__name__)
                if module.initModule(pymodule):
                    warnings = warn.find([module], _cfg, _suppressions)
                    _printWarnings(_get_unique_warnings(warnings))
                else :
                    print 'Unable to load module', pymodule.__name__
            except Exception:
                name = getattr(pymodule, '__name__', utils.safestr(pymodule))
                # FIXME: can we use it here ?
                importError(name)

        return pymodule
Exemplo n.º 11
0
def _checkOverridenMethods(func, baseClasses, warnings) :
    for baseClass in baseClasses :
        if func.func_name != utils.INIT and \
           not function.same_signature(func, baseClass) :
            err = msgs.METHOD_SIGNATURE_MISMATCH % (func.func_name, utils.safestr(baseClass))
            warnings.append(Warning(func.func_code, func.func_code, err))
            break
Exemplo n.º 12
0
def _checkBaseClassInit(moduleFilename, c, func_code, funcInfo) :
    """
    Return a list of warnings that occur for each base class whose __init__()
    is not called

    @param funcInfo: triple of functions called, code objects, return values
    @type  funcInfo: triple
    """

    warnings = []
    functionsCalled, _, returnValues = funcInfo
    for line, stackItem, dummy in returnValues :
        if stackItem.data != None :
            if not stackItem.isNone() or cfg().returnNoneFromInit :
                warn = Warning(func_code, line, msgs.RETURN_FROM_INIT)
                warnings.append(warn)

    classInit = getattr(c.classObject, utils.INIT, None)
    if cfg().baseClassInitted and classInit is not None :
        classInitInfo = _get_func_info(classInit)
        for base in getattr(c.classObject, '__bases__', None) or ():
            if not _baseInitCalled(classInitInfo, base, functionsCalled):
                warn = Warning(moduleFilename, func_code,
                               msgs.BASE_CLASS_NOT_INIT % utils.safestr(base))
                warnings.append(warn)
    return warnings
Exemplo n.º 13
0
def _baseInitCalled(classInitInfo, base, functionsCalled) :
    baseInit = getattr(base, utils.INIT, None)
    if baseInit is None or _get_func_info(baseInit) == classInitInfo :
        return 1

    initName = utils.safestr(base) + _DOT_INIT
    if functionsCalled.has_key(initName) :
        return 1

    # ok, do this the hard way, there may be aliases, so check here
    names = string.split(initName, '.')

    # first look in our list of PyCheckerModules
    moduleName = names[0]
    moduleDir = os.path.dirname(classInitInfo[0])
    pcmodule = pcmodules.getPCModule(moduleName, moduleDir)
    if pcmodule:
        obj = pcmodule.module
    else:
        # fall back to looking in sys.modules
        try:
            # i think this can raise an exception if the module is a library
            # (.so)
            obj = sys.modules[names[0]]
        except KeyError:
            return 1
    for i in range(1, len(names)) :
        obj = getattr(obj, names[i], None)
        if obj is None:
            return 0
        if functionsCalled.has_key(string.join(names[i:], '.')) :
            return 1

    return 0
Exemplo n.º 14
0
def _checkOverridenMethods(func, baseClasses, warnings) :
    for baseClass in baseClasses :
        if func.func_name != utils.INIT and \
           not function.same_signature(func, baseClass) :
            err = msgs.METHOD_SIGNATURE_MISMATCH % (func.func_name, utils.safestr(baseClass))
            warnings.append(Warning(func.func_code, func.func_code, err))
            break
Exemplo n.º 15
0
def _baseInitCalled(classInitInfo, base, functionsCalled) :
    baseInit = getattr(base, utils.INIT, None)
    if baseInit is None or _get_func_info(baseInit) == classInitInfo :
        return 1

    initName = utils.safestr(base) + _DOT_INIT
    if functionsCalled.has_key(initName) :
        return 1

    # ok, do this the hard way, there may be aliases, so check here
    names = string.split(initName, '.')

    # first look in our list of PyCheckerModules
    moduleName = names[0]
    moduleDir = os.path.dirname(classInitInfo[0])
    pcmodule = pcmodules.getPCModule(moduleName, moduleDir)
    if pcmodule:
        obj = pcmodule.module
    else:
        # fall back to looking in sys.modules
        try:
            # i think this can raise an exception if the module is a library
            # (.so)
            obj = sys.modules[names[0]]
        except KeyError:
            return 1
    for i in range(1, len(names)) :
        obj = getattr(obj, names[i], None)
        if obj is None:
            return 0
        if functionsCalled.has_key(string.join(names[i:], '.')) :
            return 1

    return 0
Exemplo n.º 16
0
    def __import__(name, globals=None, locals=None, fromlist=None):
        if globals is None:
            globals = {}
        if locals is None:
            locals = {}
        if fromlist is None:
            fromlist = []

        check = not sys.modules.has_key(name) and name[:10] != 'pychecker.'
        pymodule = _orig__import__(name, globals, locals, fromlist)
        if check:
            try:
                # FIXME: can we find a good moduleDir ?
                module = PyCheckerModule(pymodule.__name__)
                if module.initModule(pymodule):
                    warnings = warn.find([module], _cfg, _suppressions)
                    _printWarnings(_get_unique_warnings(warnings))
                else:
                    print 'Unable to load module', pymodule.__name__
            except Exception:
                name = getattr(pymodule, '__name__', utils.safestr(pymodule))
                # FIXME: can we use it here ?
                importError(name)

        return pymodule
Exemplo n.º 17
0
 def addClass(self, name):
     self.classes[name] = c = Class(name, self)
     try:
         objName = utils.safestr(c.classObject)
     except TypeError:
         # this can happen if there is a goofy __getattr__
         c.ignoreAttrs = 1
     else:
         packages = string.split(objName, '.')
         c.ignoreAttrs = packages[0] in utils.cfg().blacklist
     if not c.ignoreAttrs :
         self.__addAttributes(c, c.classObject)
Exemplo n.º 18
0
 def addClass(self, name):
     self.classes[name] = c = Class(name, self)
     try:
         objName = utils.safestr(c.classObject)
     except TypeError:
         # this can happen if there is a goofy __getattr__
         c.ignoreAttrs = 1
     else:
         packages = string.split(objName, '.')
         c.ignoreAttrs = packages[0] in cfg().blacklist
     if not c.ignoreAttrs:
         self.__addAttributes(c, c.classObject)
Exemplo n.º 19
0
def printFunction(spaces, prefix, func, className = None) :
    params = ''
    argcount = func.func_code.co_argcount
    defaultArgStart = argcount
    if func.func_defaults != None :
        defaultArgStart = argcount - len(func.func_defaults)
    for i in range(0, argcount) :
        arg = func.func_code.co_varnames[i]
        if i >= defaultArgStart :
            arg = arg + " = %s" % utils.safestr(func.func_defaults[i - defaultArgStart])
        params = params + "%s, " % arg
    params = "(%s)" % params[:-2]
    if className == None :
        className = ""
    else :
        className = className + "."
    print "%s%s%s%s%s" % (spaces, prefix, className, func.func_name, params)
Exemplo n.º 20
0
def printFunction(spaces, prefix, func, className=None):
    params = ''
    argcount = func.func_code.co_argcount
    defaultArgStart = argcount
    if func.func_defaults != None:
        defaultArgStart = argcount - len(func.func_defaults)
    for i in range(0, argcount):
        arg = func.func_code.co_varnames[i]
        if i >= defaultArgStart:
            arg = arg + " = %s" % utils.safestr(
                func.func_defaults[i - defaultArgStart])
        params = params + "%s, " % arg
    params = "(%s)" % params[:-2]
    if className == None:
        className = ""
    else:
        className = className + "."
    print "%s%s%s%s%s" % (spaces, prefix, className, func.func_name, params)
Exemplo n.º 21
0
    def __import__(name, globals=None, locals=None, fromlist=None, level=None):
        if globals is None:
            globals = {}
        if locals is None:
            locals = {}
        if fromlist is None:
            fromlist = []

        check = not sys.modules.has_key(name) and name[:10] != 'pychecker.'
        if level:
            pymodule = _orig__import__(name, globals, locals, fromlist, level)
        else:
            pymodule = _orig__import__(name, globals, locals, fromlist)
        if check :
            try :
                # FIXME: can we find a good moduleDir ?
                # based on possible module.__file__, check if it's from
                # sys.path, and if not, extract moduleDir
                moduleDir = os.path.dirname(pymodule.__file__)
                for path in sys.path:
                    if os.path.abspath(moduleDir) == os.path.abspath(path):
                        moduleDir = None
                        break

                # FIXME: could it possibly be from a higher-level package,
                # instead of the current dir ? Loop up with __init__.py ?
                module = pcmodules.PyCheckerModule(pymodule.__name__,
                    moduleDir=moduleDir)
                if module.initModule(pymodule):
                    warnings = warn.find([module], _cfg, _suppressions)
                    _printWarnings(_get_unique_warnings(warnings))
                else :
                    print 'Unable to load module', pymodule.__name__
            except Exception:
                name = getattr(pymodule, '__name__', utils.safestr(pymodule))
                # FIXME: can we use it here ?
                utils.importError(name)

        return pymodule
Exemplo n.º 22
0
    def __import__(name, globals=None, locals=None, fromlist=None, level=None):
        if globals is None:
            globals = {}
        if locals is None:
            locals = {}
        if fromlist is None:
            fromlist = []

        check = not sys.modules.has_key(name) and name[:10] != 'pychecker.'
        if level:
            pymodule = _orig__import__(name, globals, locals, fromlist, level)
        else:
            pymodule = _orig__import__(name, globals, locals, fromlist)
        if check:
            try:
                # FIXME: can we find a good moduleDir ?
                # based on possible module.__file__, check if it's from
                # sys.path, and if not, extract moduleDir
                moduleDir = os.path.dirname(pymodule.__file__)
                for path in sys.path:
                    if os.path.abspath(moduleDir) == os.path.abspath(path):
                        moduleDir = None
                        break

                # FIXME: could it possibly be from a higher-level package,
                # instead of the current dir ? Loop up with __init__.py ?
                module = pcmodules.PyCheckerModule(pymodule.__name__,
                                                   moduleDir=moduleDir)
                if module.initModule(pymodule):
                    warnings = warn.find([module], _cfg, _suppressions)
                    _printWarnings(_get_unique_warnings(warnings))
                else:
                    print 'Unable to load module', pymodule.__name__
            except Exception:
                name = getattr(pymodule, '__name__', utils.safestr(pymodule))
                # FIXME: can we use it here ?
                utils.importError(name)

        return pymodule
Exemplo n.º 23
0
def _baseInitCalled(classInitInfo, base, functionsCalled):
    baseInit = getattr(base, utils.INIT, None)
    if baseInit is None or _get_func_info(baseInit) == classInitInfo:
        return 1

    initName = utils.safestr(base) + _DOT_INIT
    if functionsCalled.has_key(initName):
        return 1

    # ok, do this the hard way, there may be aliases, so check here
    names = string.split(initName, '.')
    try:
        # i think this can raise an exception if the module is a library (.so)
        obj = sys.modules[names[0]]
    except KeyError:
        return 1
    for i in range(1, len(names)):
        obj = getattr(obj, names[i], None)
        if obj is None:
            return 0
        if functionsCalled.has_key(string.join(names[i:], '.')):
            return 1

    return 0
Exemplo n.º 24
0
def _baseInitCalled(classInitInfo, base, functionsCalled) :
    baseInit = getattr(base, utils.INIT, None)
    if baseInit is None or _get_func_info(baseInit) == classInitInfo :
        return 1

    initName = utils.safestr(base) + _DOT_INIT
    if functionsCalled.has_key(initName) :
        return 1

    # ok, do this the hard way, there may be aliases, so check here
    names = string.split(initName, '.')
    try:
        # i think this can raise an exception if the module is a library (.so)
        obj = sys.modules[names[0]]
    except KeyError:
        return 1
    for i in range(1, len(names)) :
        obj = getattr(obj, names[i], None)
        if obj is None:
            return 0
        if functionsCalled.has_key(string.join(names[i:], '.')) :
            return 1

    return 0
Exemplo n.º 25
0
def _findClassWarnings(module, c, class_code,
                       globalRefs, warnings, suppressions) :
    utils.debug("class:", class_code)
    try:
        className = utils.safestr(c.classObject)
    except TypeError:
        # goofy __getattr__
        return
    classSuppress = getSuppression(className, suppressions, warnings)
    baseClasses = c.allBaseClasses()
    for base in baseClasses :
        baseModule = utils.safestr(base)
        if '.' in baseModule :
            # make sure we handle import x.y.z
            packages = string.split(baseModule, '.')
            baseModuleDir = string.join(packages[:-1], '.')
            globalRefs[baseModuleDir] = baseModule

    # handle class variables
    if class_code is not None :
        func = function.create_fake(c.name, class_code)
        _updateFunctionWarnings(module, func, c, warnings, globalRefs, 0, 1)

    filename = module.filename()
    func_code = None
    for method in c.methods.values() :
        if method == None :
            continue
        func_code = method.function.func_code
        utils.debug("class %s: method:" % className, func_code)

        try:
            name = utils.safestr(c.classObject) + '.' + method.function.func_name
        except AttributeError:
            # func_name may not exist
            continue
        methodSuppress = getSuppression(name, suppressions, warnings)

        if cfg().checkSpecialMethods:
            funcname = method.function.func_name
            if funcname[:2] == '__' == funcname[-2:] and \
               funcname != '__init__':
                err = None
                argCount = python.SPECIAL_METHODS.get(funcname, -1)
                if argCount != -1:
                    # if the args are None, it can be any # of args
                    if argCount is not None:
                        minArgs = maxArgs = argCount
                        err = CodeChecks.getFunctionArgErr(funcname,
                                     func_code.co_argcount, minArgs, maxArgs)
                else:
                    err = msgs.NOT_SPECIAL_METHOD % funcname

                if err is not None:
                    warnings.append(Warning(filename, func_code, err))
                
        if cfg().checkOverridenMethods :
            _checkOverridenMethods(method.function, baseClasses, warnings)

        if cfg().noDocFunc and method.function.__doc__ == None :
            err = msgs.NO_FUNC_DOC % method.function.__name__
            # FIXME: is there a good reason why this passes func_code as line ?
            warnings.append(Warning(filename, func_code, err))

        _checkSelfArg(method, warnings)
        tmpModule = _getModuleFromFilename(module, func_code.co_filename)
        funcInfo = _updateFunctionWarnings(tmpModule, method, c, warnings, globalRefs)
        if func_code.co_name == utils.INIT :
            # this is a constructor
            if utils.INIT in dir(c.classObject) :
                warns = _checkBaseClassInit(filename, c, func_code, funcInfo)
                warnings.extend(warns)
            elif cfg().initDefinedInSubclass :
                err = msgs.NO_INIT_IN_SUBCLASS % c.name
                warnings.append(Warning(filename, c.getFirstLine(), err))
        if methodSuppress is not None :
            utils.popConfig()

    if c.memberRefs and cfg().membersUsed :
        memberList = c.memberRefs.keys()
        memberList.sort()
        err = msgs.UNUSED_MEMBERS % (string.join(memberList, ', '), c.name)
        warnings.append(Warning(filename, c.getFirstLine(), err))

    try:
        newStyleClass = issubclass(c.classObject, object)
    except TypeError:
        # FIXME: perhaps this should warn b/c it may be a class???
        newStyleClass = 0

    slots = c.statics.get('__slots__')
    if slots is not None and cfg().slots:
        lineNum = c.lineNums['__slots__']
        if not newStyleClass:
            err = msgs.USING_SLOTS_IN_CLASSIC_CLASS % c.name
            warnings.append(Warning(filename, lineNum, err))
        elif cfg().emptySlots:
            try:
                if len(slots.data) == 0:
                    err = msgs.EMPTY_SLOTS % c.name
                    warnings.append(Warning(filename, lineNum, err))
            except AttributeError:
                # happens when slots is an instance of a class w/o __len__
                pass

    if not newStyleClass and property is not None and cfg().classicProperties:
        for static in c.statics.keys():
            if type(getattr(c.classObject, static, None)) == property:
                err = msgs.USING_PROPERTIES_IN_CLASSIC_CLASS % (static, c.name)
                warnings.append(Warning(filename, c.lineNums[static], err))

    coerceMethod = c.methods.get('__coerce__')
    if newStyleClass and coerceMethod:
        lineNum = coerceMethod.function.func_code.co_firstlineno
        err = msgs.USING_COERCE_IN_NEW_CLASS % c.name
        warnings.append(Warning(filename, lineNum, err))

    for newClassMethodName in python.NEW_STYLE_CLASS_METHODS:
        newClassMethod = c.methods.get(newClassMethodName)
        if not newStyleClass and newClassMethod:
            lineNum = newClassMethod.function.func_code.co_firstlineno
            err = msgs.USING_NEW_STYLE_METHOD_IN_OLD_CLASS % (newClassMethodName, c.name)
            warnings.append(Warning(filename, lineNum, err))

    if cfg().noDocClass and c.classObject.__doc__ == None :
        method = c.methods.get(utils.INIT, None)
        if method != None :
            func_code = method.function.func_code
        # FIXME: check to make sure this is in our file,
        #        not a base class file???
        err = msgs.NO_CLASS_DOC % c.classObject.__name__
        warnings.append(Warning(filename, func_code, err))

    # we have to do this here, b/c checkFunction doesn't popConfig for classes
    # this allows us to have __pychecker__ apply to all methods
    # when defined at class scope
    if class_code is not None :
        utils.popConfig()

    if classSuppress is not None :
        utils.popConfig()
Exemplo n.º 26
0
 def __getitem__(self, x):
     from pychecker import utils
     return utils.safestr(x)
Exemplo n.º 27
0
def _findClassWarnings(module, c, class_code,
                       globalRefs, warnings, suppressions) :
    try:
        className = utils.safestr(c.classObject)
    except TypeError:
        # goofy __getattr__
        return
    classSuppress = getSuppression(className, suppressions, warnings)
    baseClasses = c.allBaseClasses()
    for base in baseClasses :
        baseModule = utils.safestr(base)
        if '.' in baseModule :
            # make sure we handle import x.y.z
            packages = string.split(baseModule, '.')
            baseModuleDir = string.join(packages[:-1], '.')
            globalRefs[baseModuleDir] = baseModule

    # handle class variables
    if class_code is not None :
        func = function.create_fake(c.name, class_code)
        _updateFunctionWarnings(module, func, c, warnings, globalRefs, 0, 1)

    filename = module.filename()
    func_code = None
    for method in c.methods.values() :
        if method == None :
            continue
        func_code = method.function.func_code
        utils.debug("method:", func_code)

        try:
            name = utils.safestr(c.classObject) + '.' + method.function.func_name
        except AttributeError:
            # func_name may not exist
            continue
        methodSuppress = getSuppression(name, suppressions, warnings)

        if cfg().checkSpecialMethods:
            funcname = method.function.func_name
            if funcname[:2] == '__' == funcname[-2:] and \
               funcname != '__init__':
                err = None
                argCount = python.SPECIAL_METHODS.get(funcname, -1)
                if argCount != -1:
                    # if the args are None, it can be any # of args
                    if argCount is not None:
                        minArgs = maxArgs = argCount
                        err = CodeChecks.getFunctionArgErr(funcname,
                                     func_code.co_argcount, minArgs, maxArgs)
                else:
                    err = msgs.NOT_SPECIAL_METHOD % funcname

                if err is not None:
                    warnings.append(Warning(filename, func_code, err))
                
        if cfg().checkOverridenMethods :
            _checkOverridenMethods(method.function, baseClasses, warnings)

        if cfg().noDocFunc and method.function.__doc__ == None :
            err = msgs.NO_FUNC_DOC % method.function.__name__
            # FIXME: is there a good reason why this passes func_code as line ?
            warnings.append(Warning(filename, func_code, err))

        _checkSelfArg(method, warnings)
        tmpModule = _getModuleFromFilename(module, func_code.co_filename)
        funcInfo = _updateFunctionWarnings(tmpModule, method, c, warnings, globalRefs)
        if func_code.co_name == utils.INIT :
            # this is a constructor
            if utils.INIT in dir(c.classObject) :
                warns = _checkBaseClassInit(filename, c, func_code, funcInfo)
                warnings.extend(warns)
            elif cfg().initDefinedInSubclass :
                err = msgs.NO_INIT_IN_SUBCLASS % c.name
                warnings.append(Warning(filename, c.getFirstLine(), err))
        if methodSuppress is not None :
            utils.popConfig()

    if c.memberRefs and cfg().membersUsed :
        memberList = c.memberRefs.keys()
        memberList.sort()
        err = msgs.UNUSED_MEMBERS % (string.join(memberList, ', '), c.name)
        warnings.append(Warning(filename, c.getFirstLine(), err))

    try:
        newStyleClass = issubclass(c.classObject, object)
    except TypeError:
        # FIXME: perhaps this should warn b/c it may be a class???
        newStyleClass = 0

    slots = c.statics.get('__slots__')
    if slots is not None and cfg().slots:
        lineNum = c.lineNums['__slots__']
        if not newStyleClass:
            err = msgs.USING_SLOTS_IN_CLASSIC_CLASS % c.name
            warnings.append(Warning(filename, lineNum, err))
        elif cfg().emptySlots:
            try:
                if len(slots.data) == 0:
                    err = msgs.EMPTY_SLOTS % c.name
                    warnings.append(Warning(filename, lineNum, err))
            except AttributeError:
                # happens when slots is an instance of a class w/o __len__
                pass

    if not newStyleClass and property is not None and cfg().classicProperties:
        for static in c.statics.keys():
            if type(getattr(c.classObject, static, None)) == property:
                err = msgs.USING_PROPERTIES_IN_CLASSIC_CLASS % (static, c.name)
                warnings.append(Warning(filename, c.lineNums[static], err))

    coerceMethod = c.methods.get('__coerce__')
    if newStyleClass and coerceMethod:
        lineNum = coerceMethod.function.func_code.co_firstlineno
        err = msgs.USING_COERCE_IN_NEW_CLASS % c.name
        warnings.append(Warning(filename, lineNum, err))

    for newClassMethodName in python.NEW_STYLE_CLASS_METHODS:
        newClassMethod = c.methods.get(newClassMethodName)
        if not newStyleClass and newClassMethod:
            lineNum = newClassMethod.function.func_code.co_firstlineno
            err = msgs.USING_NEW_STYLE_METHOD_IN_OLD_CLASS % (newClassMethodName, c.name)
            warnings.append(Warning(filename, lineNum, err))

    if cfg().noDocClass and c.classObject.__doc__ == None :
        method = c.methods.get(utils.INIT, None)
        if method != None :
            func_code = method.function.func_code
        # FIXME: check to make sure this is in our file,
        #        not a base class file???
        err = msgs.NO_CLASS_DOC % c.classObject.__name__
        warnings.append(Warning(filename, func_code, err))

    # we have to do this here, b/c checkFunction doesn't popConfig for classes
    # this allows us to have __pychecker__ apply to all methods
    # when defined at class scope
    if class_code is not None :
        utils.popConfig()

    if classSuppress is not None :
        utils.popConfig()