--- a/src/eric7/Utilities/ClassBrowsers/pyclbr.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Utilities/ClassBrowsers/pyclbr.py Wed Jul 13 14:55:47 2022 +0200 @@ -132,24 +132,26 @@ | (?: [^#;\\\n]* (?: \\\n )* )* ) )""", - re.VERBOSE | re.DOTALL | re.MULTILINE).search + re.VERBOSE | re.DOTALL | re.MULTILINE, +).search _commentsub = re.compile(r"""#[^\n]*\n|#[^\n]*$""").sub -_modules = {} # cache of modules we've seen +_modules = {} # cache of modules we've seen class VisibilityMixin(ClbrBaseClasses.ClbrVisibilityMixinBase): """ Mixin class implementing the notion of visibility. """ + def __init__(self): """ Constructor """ - if self.name.startswith('__'): + if self.name.startswith("__"): self.setPrivate() - elif self.name.startswith('_'): + elif self.name.startswith("_"): self.setProtected() else: self.setPublic() @@ -159,18 +161,18 @@ """ Class to represent a Python class. """ + def __init__(self, module, name, superClasses, file, lineno): """ Constructor - + @param module name of the module containing this class @param name name of this class @param superClasses list of class names this class is inherited from @param file filename containing this class @param lineno linenumber of the class definition """ - ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, - lineno) + ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, lineno) VisibilityMixin.__init__(self) @@ -178,11 +180,21 @@ """ Class to represent a Python function. """ - def __init__(self, module, name, file, lineno, signature='', separator=',', - modifierType=ClbrBaseClasses.Function.General, annotation=""): + + def __init__( + self, + module, + name, + file, + lineno, + signature="", + separator=",", + modifierType=ClbrBaseClasses.Function.General, + annotation="", + ): """ Constructor - + @param module name of the module containing this function @param name name of this function @param file filename containing this class @@ -192,9 +204,17 @@ @param modifierType type of the function @param annotation return annotation """ - ClbrBaseClasses.Function.__init__(self, module, name, file, lineno, - signature, separator, modifierType, - annotation) + ClbrBaseClasses.Function.__init__( + self, + module, + name, + file, + lineno, + signature, + separator, + modifierType, + annotation, + ) VisibilityMixin.__init__(self) @@ -202,10 +222,11 @@ """ Class to represent a class attribute. """ + def __init__(self, module, name, file, lineno): """ Constructor - + @param module name of the module containing this class @param name name of this class @param file filename containing this attribute @@ -219,43 +240,46 @@ """ Class to represent the list of public identifiers. """ + def __init__(self, module, file, lineno, idents): """ Constructor - + @param module name of the module containing this function @param file filename containing this class @param lineno linenumber of the class definition @param idents list of public identifiers """ self.module = module - self.name = '__all__' + self.name = "__all__" self.file = file self.lineno = lineno - self.identifiers = [e.replace('"', '').replace("'", "").strip() - for e in idents.split(',')] + self.identifiers = [ + e.replace('"', "").replace("'", "").strip() for e in idents.split(",") + ] class Imports: """ Class to represent the list of imported modules. """ + def __init__(self, module, file): """ Constructor - + @param module name of the module containing the import (string) @param file file name containing the import (string) """ self.module = module - self.name = 'import' + self.name = "import" self.file = file self.imports = {} - + def addImport(self, moduleName, names, lineno): """ Public method to add a list of imported names. - + @param moduleName name of the imported module (string) @param names list of names (list of strings) @param lineno line number of the import @@ -266,11 +290,11 @@ else: module = self.imports[moduleName] module.addImport(lineno, names) - + def getImport(self, moduleName): """ Public method to get an imported module item. - + @param moduleName name of the imported module (string) @return imported module item (ImportedModule) or None """ @@ -278,11 +302,11 @@ return self.imports[moduleName] else: return None - + def getImports(self): """ Public method to get all imported module names. - + @return dictionary of imported module names with name as key and list of line numbers of imports as value """ @@ -293,39 +317,40 @@ """ Class to represent an imported module. """ + def __init__(self, module, file, importedModule): """ Constructor - + @param module name of the module containing the import (string) @param file file name containing the import (string) @param importedModule name of the imported module (string) """ self.module = module - self.name = 'import' + self.name = "import" self.file = file self.importedModuleName = importedModule self.linenos = [] self.importedNames = {} # dictionary of imported names with name as key and list of line # numbers as value - + def addImport(self, lineno, importedNames): """ Public method to add a list of imported names. - + @param lineno line number of the import @param importedNames list of imported names (list of strings) """ if lineno not in self.linenos: self.linenos.append(lineno) - + for name in importedNames: if name not in self.importedNames: self.importedNames[name] = [lineno] else: self.importedNames[name].append(lineno) - + def readmodule_ex(module, path=None, inpackage=False, isPyFile=False): """ @@ -334,7 +359,7 @@ Search for MODULE in PATH and sys.path, read and parse the module and return a dictionary with one entry for each class found in the module. - + @param module name of the module file @type str @param path path the module should be searched in @@ -347,7 +372,7 @@ @rtype dict """ global _modules - + if module in _modules: # we've seen this module before... return _modules[module] @@ -361,14 +386,14 @@ f = None if inpackage: try: - f, file, (suff, mode, type) = ClassBrowsers.find_module( - module, path) + f, file, (suff, mode, type) = ClassBrowsers.find_module(module, path) except ImportError: f = None if f is None: fullpath = path[:] + sys.path[:] f, file, (suff, mode, type) = ClassBrowsers.find_module( - module, fullpath, isPyFile) + module, fullpath, isPyFile + ) if f: f.close() if type not in SUPPORTED_TYPES: @@ -382,7 +407,7 @@ # can't do anything with this module _modules[module] = {} return {} - + _modules[module] = scan(src, file, module) return _modules[module] @@ -390,7 +415,7 @@ def scan(src, file, module): """ Public method to scan the given source text. - + @param src source text to be scanned @type str @param file file name associated with the source text @@ -400,10 +425,11 @@ @return dictionary containing the extracted data @rtype dict """ + def calculateEndline(lineno, lines, indent): """ Function to calculate the end line of a class or method/function. - + @param lineno line number to start at (one based) @type int @param lines list of source lines @@ -423,23 +449,23 @@ if lineIndent <= indent: return lineno lineno += 1 - + # nothing found return -1 - + # convert eol markers the Python style src = src.replace("\r\n", "\n").replace("\r", "\n") srcLines = src.splitlines() - + dictionary = {} dict_counts = {} - + classstack = [] # stack of (class, indent) pairs conditionalsstack = [] # stack of indents of conditional defines deltastack = [] deltaindent = 0 deltaindentcalculated = False - + lineno, last_lineno_pos = 1, 0 i = 0 modifierType = ClbrBaseClasses.Function.General @@ -453,18 +479,18 @@ if m.start("MethodModifier") >= 0: modifierIndent = _indent(m.group("MethodModifierIndent")) modifierType = m.group("MethodModifierType") - + elif m.start("Method") >= 0: # found a method definition or function thisindent = _indent(m.group("MethodIndent")) meth_name = m.group("MethodName") meth_sig = m.group("MethodSignature") - meth_sig = meth_sig.replace('\\\n', '') - meth_sig = _commentsub('', meth_sig) + meth_sig = meth_sig.replace("\\\n", "") + meth_sig = _commentsub("", meth_sig) meth_ret = m.group("MethodReturnAnnotation") - meth_ret = meth_ret.replace('\\\n', '') - meth_ret = _commentsub('', meth_ret) - lineno += src.count('\n', last_lineno_pos, start) + meth_ret = meth_ret.replace("\\\n", "") + meth_ret = _commentsub("", meth_ret) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start if modifierType and modifierIndent == thisindent: if modifierType == "@staticmethod": @@ -484,10 +510,7 @@ deltaindentcalculated = True thisindent -= deltaindent else: - while ( - conditionalsstack and - conditionalsstack[-1] >= thisindent - ): + while conditionalsstack and conditionalsstack[-1] >= thisindent: del conditionalsstack[-1] if deltastack: del deltastack[-1] @@ -500,21 +523,32 @@ cur_class = classstack[-1][0] if cur_class: # it's a method/nested def - f = Function(None, meth_name, - file, lineno, meth_sig, annotation=meth_ret, - modifierType=modifier) + f = Function( + None, + meth_name, + file, + lineno, + meth_sig, + annotation=meth_ret, + modifierType=modifier, + ) cur_class._addmethod(meth_name, f) else: f = None else: # it's a function - f = Function(module, meth_name, - file, lineno, meth_sig, annotation=meth_ret, - modifierType=modifier) + f = Function( + module, + meth_name, + file, + lineno, + meth_sig, + annotation=meth_ret, + modifierType=modifier, + ) if meth_name in dict_counts: dict_counts[meth_name] += 1 - meth_name = "{0}_{1:d}".format( - meth_name, dict_counts[meth_name]) + meth_name = "{0}_{1:d}".format(meth_name, dict_counts[meth_name]) else: dict_counts[meth_name] = 0 dictionary[meth_name] = f @@ -522,7 +556,7 @@ endlineno = calculateEndline(lineno, srcLines, thisindent) f.setEndLine(endlineno) classstack.append((f, thisindent)) # Marker for nested fns - + # reset the modifier settings modifierType = ClbrBaseClasses.Function.General modifierIndent = -1 @@ -536,22 +570,22 @@ # close all classes indented at least as much while classstack and classstack[-1][1] >= thisindent: del classstack[-1] - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start class_name = m.group("ClassName") inherit = m.group("ClassSupers") if inherit: # the class inherits from other classes inherit = inherit[1:-1].strip() - inherit = _commentsub('', inherit) + inherit = _commentsub("", inherit) names = [] - for n in inherit.split(','): + for n in inherit.split(","): n = n.strip() if n in dictionary: # we know this super class n = dictionary[n] else: - c = n.split('.') + c = n.split(".") if len(c) > 1: # super class # is of the @@ -574,24 +608,19 @@ deltaindentcalculated = True thisindent -= deltaindent else: - while ( - conditionalsstack and - conditionalsstack[-1] >= thisindent - ): + while conditionalsstack and conditionalsstack[-1] >= thisindent: del conditionalsstack[-1] if deltastack: del deltastack[-1] deltaindentcalculated = False # remember this class - cur_class = Class(module, class_name, inherit, - file, lineno) + cur_class = Class(module, class_name, inherit, file, lineno) endlineno = calculateEndline(lineno, srcLines, thisindent) cur_class.setEndLine(endlineno) if not classstack: if class_name in dict_counts: dict_counts[class_name] += 1 - class_name = "{0}_{1:d}".format( - class_name, dict_counts[class_name]) + class_name = "{0}_{1:d}".format(class_name, dict_counts[class_name]) else: dict_counts[class_name] = 0 dictionary[class_name] = cur_class @@ -600,16 +629,14 @@ classstack.append((cur_class, thisindent)) elif m.start("Attribute") >= 0: - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start index = -1 while index >= -len(classstack): - if ( - classstack[index][0] is not None and - not isinstance(classstack[index][0], Function) + if classstack[index][0] is not None and not isinstance( + classstack[index][0], Function ): - attr = Attribute( - module, m.group("AttributeName"), file, lineno) + attr = Attribute(module, m.group("AttributeName"), file, lineno) classstack[index][0]._addattribute(attr) break else: @@ -617,24 +644,26 @@ elif m.start("Main") >= 0: # 'main' part of the script, reset class stack - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start classstack = [] elif m.start("Variable") >= 0: thisindent = _indent(m.group("VariableIndent")) variable_name = m.group("VariableName") - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start if thisindent == 0 or not classstack: # global variable, reset class stack first classstack = [] - + if "@@Globals@@" not in dictionary: dictionary["@@Globals@@"] = ClbrBaseClasses.ClbrBase( - module, "Globals", file, lineno) + module, "Globals", file, lineno + ) dictionary["@@Globals@@"]._addglobal( - Attribute(module, variable_name, file, lineno)) + Attribute(module, variable_name, file, lineno) + ) else: index = -1 while index >= -len(classstack): @@ -643,46 +672,51 @@ else: if isinstance(classstack[index][0], Class): classstack[index][0]._addglobal( - Attribute(module, variable_name, file, lineno)) + Attribute(module, variable_name, file, lineno) + ) break elif m.start("Publics") >= 0: idents = m.group("Identifiers") - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start pubs = Publics(module, file, lineno, idents) - dictionary['__all__'] = pubs - + dictionary["__all__"] = pubs + elif m.start("Import") >= 0: - #- import module - names = [n.strip() for n in - "".join(m.group("ImportList").splitlines()) - .replace("\\", "").split(',')] - lineno += src.count('\n', last_lineno_pos, start) + # - import module + names = [ + n.strip() + for n in "".join(m.group("ImportList").splitlines()) + .replace("\\", "") + .split(",") + ] + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start if "@@Import@@" not in dictionary: dictionary["@@Import@@"] = Imports(module, file) for name in names: dictionary["@@Import@@"].addImport(name, [], lineno) - + elif m.start("ImportFrom") >= 0: - #- from module import stuff + # - from module import stuff mod = m.group("ImportFromPath") - namesLines = (m.group("ImportFromList") - .replace("(", "").replace(")", "") - .replace("\\", "") - .strip().splitlines()) - namesLines = [line.split("#")[0].strip() - for line in namesLines] - names = [n.strip() for n in - "".join(namesLines) - .split(',')] - lineno += src.count('\n', last_lineno_pos, start) + namesLines = ( + m.group("ImportFromList") + .replace("(", "") + .replace(")", "") + .replace("\\", "") + .strip() + .splitlines() + ) + namesLines = [line.split("#")[0].strip() for line in namesLines] + names = [n.strip() for n in "".join(namesLines).split(",")] + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start if "@@Import@@" not in dictionary: dictionary["@@Import@@"] = Imports(module, file) dictionary["@@Import@@"].addImport(mod, names, lineno) - + elif m.start("ConditionalDefine") >= 0: # a conditional function/method definition thisindent = _indent(m.group("ConditionalDefineIndent")) @@ -692,35 +726,36 @@ del deltastack[-1] conditionalsstack.append(thisindent) deltaindentcalculated = False - + elif m.start("CodingLine") >= 0: # a coding statement coding = m.group("Coding") - lineno += src.count('\n', last_lineno_pos, start) + lineno += src.count("\n", last_lineno_pos, start) last_lineno_pos = start if "@@Coding@@" not in dictionary: dictionary["@@Coding@@"] = ClbrBaseClasses.Coding( - module, file, lineno, coding) + module, file, lineno, coding + ) - if '__all__' in dictionary: + if "__all__" in dictionary: # set visibility of all top level elements - pubs = dictionary['__all__'] + pubs = dictionary["__all__"] for key in dictionary: - if key == '__all__' or key.startswith("@@"): + if key == "__all__" or key.startswith("@@"): continue if key in pubs.identifiers: dictionary[key].setPublic() else: dictionary[key].setPrivate() - del dictionary['__all__'] - + del dictionary["__all__"] + return dictionary def _indent(ws): """ Module function to return the indentation depth. - + @param ws the whitespace to be checked (string) @return length of the whitespace string (integer) """