#!/usr/bin/env python

# Copyright (c) 2001-2002, MetaSlash Inc.  All rights reserved.
# Portions Copyright (c) 2005, Google, Inc. All rights reserved.

"""
Print out warnings from Python source files.
"""

import os.path
import sys
import string
import types
import traceback
import imp
import re

from pychecker import OP
from pychecker import Stack
from pychecker import function
from pychecker import python
from pychecker import pcmodules

from pychecker import msgs
from pychecker import utils
from pychecker import CodeChecks
from pychecker.Warning import Warning


def cfg() :
    return utils.cfg()

def _checkSelfArg(method, warnings) :
    """Return a Warning if there is no self parameter or
       the first parameter to a method is not self."""

    if not cfg().methodArgName:
        return

    code = method.function.func_code
    err = None
    if method.isStaticMethod():
        if code.co_argcount > 0 and cfg().methodArgName == code.co_varnames[0]:
            err = msgs.SELF_IS_ARG % 'staticmethod'
    elif code.co_argcount < 1: 
        err = msgs.NO_METHOD_ARGS % cfg().methodArgName
    else:
        if method.isClassMethod():
            if code.co_varnames[0] not in cfg().classmethodArgNames:
                err = msgs.SELF_NOT_FIRST_ARG % \
                      (cfg().classmethodArgNames, 'class')
        elif code.co_varnames[0] != cfg().methodArgName:
            err = msgs.SELF_NOT_FIRST_ARG % (cfg().methodArgName, '')

    if err is not None :
        warnings.append(Warning(code, code, err))


def _checkNoSelfArg(func, warnings) :
    "Return a Warning if there is a self parameter to a function."

    code = func.function.func_code
    if code.co_argcount > 0 and cfg().methodArgName in code.co_varnames:
        warnings.append(Warning(code, code, msgs.SELF_IS_ARG % 'function'))


def _checkSubclass(c1, c2):
    try:
        return issubclass(c1.classObject, c2.classObject)
    except (TypeError, AttributeError):
        return 0


_IGNORE_RETURN_TYPES = ( Stack.TYPE_FUNC_RETURN, Stack.TYPE_ATTRIBUTE,
                         Stack.TYPE_GLOBAL, Stack.TYPE_COMPARISON,
                         Stack.TYPE_UNKNOWN)

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)


def _checkComplex(code, maxValue, value, func, err) :
    if maxValue and value > maxValue :
        line = func.function.func_code.co_firstlineno
        code.addWarning(err % (func.function.__name__, value), line)


def _checkCode(code, codeSource) :
    while code.index < code.maxCode :
        op, oparg, operand = code.popNextOp()
        dispatch_func = CodeChecks.DISPATCH[op]
        if dispatch_func is not None :
            dispatch_func(oparg, operand, codeSource, code)

def _name_unused(var) :
    if var in cfg().unusedNames :
        return 0
    for name in cfg().unusedNames :
        if name != '_' and utils.startswith(var, name) :
            return 0
    return 1

def _checkUnusedParam(var, line, func, code) :
    if line is not None and line == 0 and _name_unused(var) :
        if ((cfg().ignoreSelfUnused or var != cfg().methodArgName) and
            (cfg().varArgumentsUsed or func.varArgName() != var)) :
            code.addWarning(msgs.UNUSED_PARAMETER % var, code.func_code)

def _handleNestedCode(func_code, code, codeSource):
    nested = not (codeSource.main or codeSource.in_class)
    if func_code.co_name == utils.LAMBDA or nested:
        utils.debug(' handling nested code')
        varnames = None
        if nested and func_code.co_name != utils.LAMBDA:
            varnames = func_code.co_varnames + \
                     codeSource.calling_code[-1].function.func_code.co_varnames
        # save the original return value and restore after checking
        returnValues = code.returnValues
        code.init(function.create_fake(func_code.co_name, func_code, {},
                                       varnames))
        _checkCode(code, codeSource)
        code.returnValues = returnValues

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


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

    # 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 func_code in code.codeObjects.values() :
            _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
        locals = len(code.func_code.co_varnames) - args
        _checkComplex(code, cfg().maxArgs, args, func, msgs.TOO_MANY_ARGS)
        _checkComplex(code, cfg().maxLocals, locals, 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
    return (code.warnings, code.globalRefs, code.functionsCalled,
            code.codeObjects.values(), code.returnValues)


def _getUnused(module, globalRefs, dict, msg, filterPrefix = None) :
    "Return a list of warnings for unused globals"

    warnings = []
    for ref in dict.keys() :
        check = not filterPrefix or utils.startswith(ref, filterPrefix)
        if check and globalRefs.get(ref) == None :
            lineInfo = module.moduleLineNums.get(ref)
            if lineInfo:
                warnings.append(Warning(lineInfo[0], lineInfo[1], msg % ref))
    return warnings


def _get_func_info(method) :
    try:
        fc = getattr(method.im_func, 'func_code', None)
        if fc is not None :
            return fc.co_filename, fc.co_firstlineno
    except AttributeError:
        # if the object derives from any object in 2.2,
        # the builtin methods are wrapper_descriptors and
        # have no im_func attr
        pass
    return None, None

_DOT_INIT = '.' + utils.INIT

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

def _checkBaseClassInit(moduleFilename, c, func_code, funcInfo) :
    """Return a list of warnings that occur
       for each base class whose __init__() is not called"""

    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


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


def _updateFunctionWarnings(module, func, c, warnings, globalRefs,
                            main = 0, in_class = 0) :
    "Update function warnings and global references"

    newWarnings, newGlobalRefs, funcs, codeObjects, returnValues = \
                 _checkFunction(module, func, c, main, in_class)
    warnings.extend(newWarnings)
    globalRefs.update(newGlobalRefs)

    return funcs, codeObjects, returnValues


def getBlackList(moduleList) :
    blacklist = []
    for badBoy in moduleList :
        if badBoy[-3:] == ".py":
            badBoy = badBoy[0:-3]
        try :
            file, path, flags = imp.find_module(badBoy)
            if file :
                file.close()
            # apparently, imp.find_module can return None, path, (triple)
            # This happened to me with twisted 2.2.0 in a separate path
            if path:
                blacklist.append(normalize_path(path))
        except ImportError :
            pass
    return blacklist

def getStandardLibraries() :
    """
    Return a list of standard libraries.

    @rtype: list of str or None
    """
    if cfg().ignoreStandardLibrary :
        try :
            from distutils import sysconfig

            std_libs = [
                sysconfig.get_python_lib(plat_specific=0),
                sysconfig.get_python_lib(plat_specific=1)
            ]
            ret = []
            for std_lib in std_libs:
                path = os.path.split(std_lib)
                if path[1] == 'site-packages' :
                    ret.append(path[0])
            return ret
        except ImportError :
            return None

def normalize_path(path):
    return os.path.normpath(os.path.normcase(path))

def removeWarnings(warnings, blacklist, std_lib, cfg):
    """
    @param blacklist: list of absolute paths not to warn for
    @type  blacklist: str
    @param std_lib:   list of standard library directories
    @type  std_lib:   list of str or None
    """
    if std_lib is not None:
        std_lib = [normalize_path(p) for p in std_lib]
    for index in range(len(warnings)-1, -1, -1) :
        filename = normalize_path(warnings[index].file)
        # the blacklist contains paths to packages and modules we do not
        # want warnings for
        # when we find a match, make sure we continue the warnings for loop
        found = False
        for path in blacklist:
            if not found and filename.startswith(path):
                found = True
                del warnings[index]
        if found:
            continue
        if std_lib:
            found = False
            for path in std_lib:
                if not found and utils.startswith(filename, path) :
                    found = True
                    del warnings[index]
            if found:
                continue
        elif cfg.only:
            # ignore files not specified on the cmd line if requested
            if os.path.abspath(filename) not in cfg.files:
                del warnings[index]
                continue

        # filter by warning/error level if requested
        if cfg.level and warnings[index].level < cfg.level:
            del warnings[index]

    if cfg.limit:
        # sort by severity first, then normal sort (by file/line)
        warnings.sort(lambda a, b: cmp(a.level, b.level) or cmp(a, b))

        # strip duplicates
        lastWarning = None
        for index in range(len(warnings)-1, -1, -1):
            warning = warnings[index]

            # remove duplicate warnings
            if lastWarning is not None and cmp(lastWarning, warning) == 0:
                del warnings[index]
            else:
                lastWarning = warning

        num_ignored = len(warnings) - cfg.limit
        if num_ignored > 0:
            del warnings[:-cfg.limit]
            msg = msgs.TOO_MANY_WARNINGS % num_ignored
            warnings.append(Warning('', 0, msg))

    return warnings


class _SuppressionError(Exception) :
    pass

def _updateSuppressions(suppress, warnings) :
    if not utils.updateCheckerArgs(suppress, 'suppressions', 0, warnings) :
        utils.popConfig()
        raise _SuppressionError

_CLASS_NAME_RE = re.compile("<class '([A-Za-z0-9.]+)'>(\\..+)?")

def getSuppression(name, suppressions, warnings) :
    try :
        utils.pushConfig()

        # cheesy hack to deal with new-style classes.  i don't see a
        # better way to get the name, '<' is an invalid identifier, so
        # we can reliably check it and extract name from:
        # <class 'class-name'>[.identifier[.identifier]...]
        matches = _CLASS_NAME_RE.match(name)
        if matches:
            # pull out the names and make a complete identifier (ignore None)
            name = string.join(filter(None, matches.groups()), '')

        suppress = suppressions[0].get(name, None)
        if suppress is not None :
            _updateSuppressions(suppress, warnings)

        regexList = suppressions[1].keys()
        regexList.sort()
        for regex in regexList :
            match = regex.match(name)
            if match and match.group() == name :
                suppress = 1
                _updateSuppressions(suppressions[1][regex], warnings)

        if not suppress :
            utils.popConfig()

        return suppress
    except _SuppressionError :
        return None

def _findFunctionWarnings(module, globalRefs, warnings, suppressions) :
    for func in module.functions.values() :
        func_code = func.function.func_code
        utils.debug("function:", func_code)

        name = '%s.%s' % (module.moduleName, func.function.__name__)
        suppress = getSuppression(name, suppressions, warnings)
        if cfg().noDocFunc and func.function.__doc__ == None :
            err = msgs.NO_FUNC_DOC % func.function.__name__
            warnings.append(Warning(module.filename(), func_code, err))

        _checkNoSelfArg(func, warnings)
        _updateFunctionWarnings(module, func, None, warnings, globalRefs)
        if suppress is not None :
            utils.popConfig()

def _getModuleFromFilename(module, filename):
    if module.filename() != filename:
        for m in module.modules.values():
            if m.filename() == filename:
                return m
    return module

# Create object for non-2.2 interpreters, any class object will do
try:
    if object: pass
except NameError:
    object = _SuppressionError

# Create property for pre-2.2 interpreters
try :
    if property: pass
except NameError:
    property = None

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__
            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 :
            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()


def find(moduleList, initialCfg, suppressions = None) :
    "Return a list of warnings found in the module list"

    if suppressions is None :
        suppressions = {}, {}

    utils.initConfig(initialCfg)

    warnings = []
    for module in moduleList :
        if module.moduleName in cfg().blacklist :
            continue

        modSuppress = getSuppression(module.moduleName, suppressions, warnings)
        globalRefs, classCodes = {}, {}

        # main_code can be null if there was a syntax error
        if module.main_code != None :
            funcInfo = _updateFunctionWarnings(module, module.main_code,
                                               None, warnings, globalRefs, 1)
            for code in funcInfo[1] :
                classCodes[code.co_name] = code

        _findFunctionWarnings(module, globalRefs, warnings, suppressions)

        for c in module.classes.values() :
            _findClassWarnings(module, c, classCodes.get(c.name),
                               globalRefs, warnings, suppressions)

        if cfg().noDocModule and \
           module.module != None and module.module.__doc__ == None :
            warnings.append(Warning(module.filename(), 1, msgs.NO_MODULE_DOC))

        if cfg().allVariablesUsed or cfg().privateVariableUsed :
            prefix = None
            if not cfg().allVariablesUsed :
                prefix = "_"
            for ignoreVar in cfg().variablesToIgnore + cfg().unusedNames :
                globalRefs[ignoreVar] = ignoreVar
            warnings.extend(_getUnused(module, globalRefs, module.variables,
                                       msgs.VAR_NOT_USED, prefix))
        if cfg().importUsed :
            if module.moduleName != utils.INIT or cfg().packageImportUsed :
                # always ignore readline module, if [raw_]input() is used
                if globalRefs.has_key('input') or \
                   globalRefs.has_key('raw_input'):
                    globalRefs['readline'] = 0
                warnings.extend(_getUnused(module, globalRefs, module.modules,
                                           msgs.IMPORT_NOT_USED))

        if module.main_code != None :
            utils.popConfig()
        if modSuppress is not None :
            utils.popConfig()

    std_lib = None
    if cfg().ignoreStandardLibrary :
        std_lib = getStandardLibraries()
    return removeWarnings(warnings, getBlackList(cfg().blacklist), std_lib,
                          cfg())

if 0:
    # if you want to test w/psyco, include this
    import psyco
    psyco.bind(_checkCode)
