📄 checker.py
字号:
def allBaseClasses(self, c = None) : "Return a list of all base classes for this class and it's subclasses" baseClasses = [] if c == None : c = self.classObject for base in c.__bases__ : baseClasses = baseClasses + [ base ] + self.allBaseClasses(base) return baseClasses def __getMethodName(self, func_name, className = None) : if func_name[0:2] == '__' and func_name[-2:] != '__' : if className == None : className = self.name if className[0] != '_' : className = '_' + className func_name = className + func_name return func_name def addMethod(self, method, methodName = None) : if type(method) == types.StringType : self.methods[method] = None else : assert methodName is not None, "must supply methodName" self.methods[methodName] = function.Function(method, 1) def addMethods(self, classObject) : for classToken in _getClassTokens(classObject) : token = getattr(classObject, classToken, None) if token is None: continue # Looks like a method. Need to code it this way to # accommodate ExtensionClass and Python 2.2. Yecchh. if (hasattr(token, "func_code") and hasattr(token.func_code, "co_argcount")): self.addMethod(token, token.__name__) elif hasattr(token, '__get__') and \ not hasattr(token, '__set__') and \ type(token) is not types.ClassType : self.addMethod(getattr(token, '__name__', classToken)) else : self.members[classToken] = type(token) self.memberRefs[classToken] = None self.cleanupMemberRefs() # add standard methods for methodName in ('__class__',) : self.addMethod(methodName, classObject.__name__) def addMembers(self, classObject) : if not cfg().onlyCheckInitForMembers : for classToken in _getClassTokens(classObject) : method = getattr(classObject, classToken, None) if type(method) == types.MethodType : self.addMembersFromMethod(method.im_func) else: try: self.addMembersFromMethod(classObject.__init__.im_func) except AttributeError: pass def addMembersFromMethod(self, method) : if not hasattr(method, 'func_code') : return func_code, code, i, maxCode, extended_arg = OP.initFuncCode(method) stack = [] while i < maxCode : op, oparg, i, extended_arg = OP.getInfo(code, i, extended_arg) if op >= OP.HAVE_ARGUMENT : operand = OP.getOperand(op, func_code, oparg) if OP.LOAD_CONST(op) or OP.LOAD_FAST(op) : stack.append(operand) elif OP.STORE_ATTR(op) : if len(stack) > 0 : if stack[-1] == cfg().methodArgName: value = None if len(stack) > 1 : value = type(stack[-2]) self.members[operand] = value self.memberRefs[operand] = None stack = [] self.cleanupMemberRefs() def cleanupMemberRefs(self) : try : del self.memberRefs[Config.CHECKER_VAR] except KeyError : pass def abstractMethod(self, m): """Return 1 if method is abstract, None if not An abstract method always raises an exception. """ if not self.methods.get(m, None): return None func_code, bytes, i, maxCode, extended_arg = \ OP.initFuncCode(self.methods[m].function) # abstract if the first conditional is RAISE_VARARGS while i < maxCode: op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg) if OP.RAISE_VARARGS(op): return 1 if OP.conditional(op): break return None def isAbstract(self): """Return the method names that make a class abstract. An abstract class has at least one abstract method.""" result = [] for m in self.methods.keys(): if self.abstractMethod(m): result.append(m) return resultdef _getLineInFile(moduleName, linenum): line = '' file, filename, smt = _findModule(moduleName) try: lines = file.readlines() line = string.rstrip(lines[linenum - 1]) except (IOError, IndexError): pass file.close() return linedef importError(moduleName): 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 = str(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, 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: global _output txt = _(" Caught exception importing module %s:\n") % moduleName _output.AddLines(txt) try: tbinfo = traceback.extract_tb(tb) except: tbinfo = [] txt = _(" Unable to format traceback\n") _output.AddLines(txt) for filename, line, func, text in tbinfo[1:]: txt = _(" File \"%s\", line %d") % (filename, line) _output.AddLines(txt) if func != "?": txt = _(", in %s()") % func _output.AddLines(txt) _output.AddLines("\n") if text: txt = _(" %s\n") % text _output.AddLines(txt) # And finally print the exception type and value. # Careful formatting exc_value -- can fail for some user exceptions txt = " %s: " % exc_name _output.AddLines(txt) try: txt = str(exc_value) + '\n' _output.AddLines(txt) except: txt = _('**error formatting exception value**\n') _output.AddLines(txt)def _getPyFile(filename): """Return the file and '.py' filename from a filename which could end with .py, .pyc, or .pyo""" if filename[-1] in 'oc' and filename[-4:-1] == '.py': return filename[:-1] return filenameclass Module : "Class to hold all information for a module" def __init__(self, moduleName, check = 1, fullpath = None) : self.moduleName = moduleName self.variables = {} self.functions = {} self.classes = {} self.modules = {} self.moduleLineNums = {} self.attributes = [ '__dict__' ] self.main_code = None self.module = None self.check = check self.fullpath = fullpath _allModules[moduleName] = self def __str__(self) : return self.moduleName __repr__ = utils.std_repr def addVariable(self, var, varType) : self.variables[var] = Variable(var, varType) def addFunction(self, func) : self.functions[func.__name__] = function.Function(func) def __addAttributes(self, c, classObject) : for base in classObject.__bases__ : self.__addAttributes(c, base) c.addMethods(classObject) c.addMembers(classObject) def addClass(self, name) : self.classes[name] = c = Class(name, self.module) try: objName = str(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 addModule(self, name) : module = _allModules.get(name, None) if module is None : self.modules[name] = module = Module(name, 0) if imp.is_builtin(name) == 0 : module.load() else : globalModule = globals().get(name) if globalModule : module.attributes.extend(dir(globalModule)) else : self.modules[name] = module def filename(self) : try : filename = self.module.__file__ except AttributeError : filename = self.moduleName return _getPyFile(filename) def load(self, warnings = None): try : # there's no need to reload modules we already have global _output, _statusDlg, _count txt = _("Loading Module %s\n") % self.moduleName _output.AddLines(txt) _count += 1 if _count == 100: _count = 95 _statusDlg.Update(_count, txt) module = sys.modules.get(self.moduleName) if module : if not _allModules[self.moduleName].module : return self._initModule(module) return 1 return self._initModule(self.setupMainCode()) except (SystemExit, KeyboardInterrupt) : exc_type, exc_value, exc_tb = sys.exc_info() raise exc_type, exc_value except SyntaxError, (message, (fileName, line, col, text)): # ActiveGrid: added this for better feedback when module couldn't be loaded. w = Warning(self.fullpath, line, _("Syntax Error: %s\n%s\n%s^error near here") % (message, text, ' '*(col-1))) warnings.append(w) return 0 except: exc_type, exc_value, exc_tb = sys.exc_info() w = Warning(self.moduleName, 1, "%s: %s.\nUnable to import module %s." % (exc_type, exc_value, self.moduleName)) warnings.append(w) importError(self.moduleName) return 0 def initModule(self, module) : if not self.module: filename = _getPyFile(module.__file__) if string.lower(filename[-3:]) == '.py':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -