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)
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)
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)
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)
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)
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)
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')
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
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
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 _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 __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
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)
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)
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)
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)
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
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
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
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
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()
def __getitem__(self, x): from pychecker import utils return utils.safestr(x)
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()