--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py Sat May 20 19:50:13 2023 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py Sun May 21 15:26:11 2023 +0200 @@ -10,7 +10,6 @@ import ast import copy import re -import sys class ImportsChecker: @@ -23,11 +22,6 @@ "I101", "I102", "I103", - ## Imports order - "I201", - "I202", - "I203", - "I204", ## Various other import related "I901", "I902", @@ -65,14 +59,6 @@ self.__tree = copy.deepcopy(tree) self.__args = args - # parameters for import sorting - if args["SortOrder"] == "native": - self.__sortingFunction = sorted - else: - # naturally is the default sort order - self.__sortingFunction = self.__naturally - self.__sortCaseSensitive = args["SortCaseSensitive"] - # statistics counters self.counters = {} @@ -81,7 +67,6 @@ checkersWithCodes = [ (self.__checkLocalImports, ("I101", "I102", "I103")), - (self.__checkImportOrder, ("I201", "I202", "I203", "I204")), (self.__tidyImports, ("I901", "I902", "I903", "I904")), ] @@ -154,230 +139,6 @@ for check in self.__checkers: check() - def getStandardModules(self): - """ - Public method to get a list of modules of the standard library. - - @return set of builtin modules - @rtype set of str - """ - try: - return sys.stdlib_module_names - except AttributeError: - return { - "__future__", - "__main__", - "_dummy_thread", - "_thread", - "abc", - "aifc", - "argparse", - "array", - "ast", - "asynchat", - "asyncio", - "asyncore", - "atexit", - "audioop", - "base64", - "bdb", - "binascii", - "binhex", - "bisect", - "builtins", - "bz2", - "calendar", - "cgi", - "cgitb", - "chunk", - "cmath", - "cmd", - "code", - "codecs", - "codeop", - "collections", - "colorsys", - "compileall", - "concurrent", - "configparser", - "contextlib", - "contextvars", - "copy", - "copyreg", - "cProfile", - "crypt", - "csv", - "ctypes", - "curses", - "dataclasses", - "datetime", - "dbm", - "decimal", - "difflib", - "dis", - "distutils", - "doctest", - "dummy_threading", - "email", - "encodings", - "ensurepip", - "enum", - "errno", - "faulthandler", - "fcntl", - "filecmp", - "fileinput", - "fnmatch", - "formatter", - "fractions", - "ftplib", - "functools", - "gc", - "getopt", - "getpass", - "gettext", - "glob", - "grp", - "gzip", - "hashlib", - "heapq", - "hmac", - "html", - "http", - "imaplib", - "imghdr", - "imp", - "importlib", - "inspect", - "io", - "ipaddress", - "itertools", - "json", - "keyword", - "lib2to3", - "linecache", - "locale", - "logging", - "lzma", - "mailbox", - "mailcap", - "marshal", - "math", - "mimetypes", - "mmap", - "modulefinder", - "msilib", - "msvcrt", - "multiprocessing", - "netrc", - "nis", - "nntplib", - "numbers", - "operator", - "optparse", - "os", - "ossaudiodev", - "parser", - "pathlib", - "pdb", - "pickle", - "pickletools", - "pipes", - "pkgutil", - "platform", - "plistlib", - "poplib", - "posix", - "pprint", - "profile", - "pstats", - "pty", - "pwd", - "py_compile", - "pyclbr", - "pydoc", - "queue", - "quopri", - "random", - "re", - "readline", - "reprlib", - "resource", - "rlcompleter", - "runpy", - "sched", - "secrets", - "select", - "selectors", - "shelve", - "shlex", - "shutil", - "signal", - "site", - "smtpd", - "smtplib", - "sndhdr", - "socket", - "socketserver", - "spwd", - "sqlite3", - "ssl", - "stat", - "statistics", - "string", - "stringprep", - "struct", - "subprocess", - "sunau", - "symbol", - "symtable", - "sys", - "sysconfig", - "syslog", - "tabnanny", - "tarfile", - "telnetlib", - "tempfile", - "termios", - "test", - "textwrap", - "threading", - "time", - "timeit", - "tkinter", - "token", - "tokenize", - "trace", - "traceback", - "tracemalloc", - "tty", - "turtle", - "turtledemo", - "types", - "typing", - "unicodedata", - "unittest", - "urllib", - "uu", - "uuid", - "venv", - "warnings", - "wave", - "weakref", - "webbrowser", - "winreg", - "winsound", - "wsgiref", - "xdrlib", - "xml", - "xmlrpc", - "zipapp", - "zipfile", - "zipimport", - "zlib", - "zoneinfo", - } - ####################################################################### ## Local imports ## @@ -399,218 +160,6 @@ self.__error(node.lineno - 1, node.col_offset, reason) ####################################################################### - ## Import order - ## - ## adapted from: flake8-alphabetize v0.0.18 - ####################################################################### - - def __checkImportOrder(self): - """ - Private method to check the order of import statements. - """ - from .ImportNode import ImportNode - - errors = [] - imports = [] - importNodes, listNode = self.__findNodes(self.__tree) - - # check for an error in '__all__' - allError = self.__findErrorInAll(listNode) - if allError is not None: - errors.append(allError) - - for importNode in importNodes: - if isinstance(importNode, ast.Import) and len(importNode.names) > 1: - # skip suck imports because its already handled by pycodestyle - continue - - imports.append( - ImportNode( - self.__args.get("ApplicationPackageNames", []), - importNode, - self, - self.__args.get("SortIgnoringStyle", False), - self.__args.get("SortFromFirst", False), - ) - ) - - lenImports = len(imports) - if lenImports > 0: - p = imports[0] - if p.error is not None: - errors.append(p.error) - - if lenImports > 1: - for n in imports[1:]: - if n.error is not None: - errors.append(n.error) - - if n == p: - if self.__args.get("CombinedAsImports", False) or ( - not n.asImport and not p.asImport - ): - errors.append((n.node, "I203", str(p), str(n))) - elif n < p: - errors.append((n.node, "I201", str(n), str(p))) - - p = n - - for error in errors: - if not self.__ignoreCode(error[1]): - node = error[0] - reason = error[1] - args = error[2:] - self.__error(node.lineno - 1, node.col_offset, reason, *args) - - def __findNodes(self, tree): - """ - Private method to find all import and import from nodes of the given - tree. - - @param tree reference to the ast node tree to be parsed - @type ast.AST - @return tuple containing a list of import nodes and the '__all__' node - @rtype tuple of (ast.Import | ast.ImportFrom, ast.List | ast.Tuple) - """ - importNodes = [] - listNode = None - - if isinstance(tree, ast.Module): - body = tree.body - - for n in body: - if isinstance(n, (ast.Import, ast.ImportFrom)): - importNodes.append(n) - - elif isinstance(n, ast.Assign): - for t in n.targets: - if isinstance(t, ast.Name) and t.id == "__all__": - value = n.value - - if isinstance(value, (ast.List, ast.Tuple)): - listNode = value - - return importNodes, listNode - - def __findErrorInAll(self, node): - """ - Private method to check the '__all__' node for errors. - - @param node reference to the '__all__' node - @type ast.List or ast.Tuple - @return tuple containing a reference to the node and an error code - @rtype rtype tuple of (ast.List | ast.Tuple, str) - """ - if node is not None: - actualList = [] - for el in node.elts: - if isinstance(el, ast.Constant): - actualList.append(el.value) - elif isinstance(el, ast.Str): - actualList.append(el.s) - else: - # Can't handle anything that isn't a string literal - return None - - expectedList = self.sorted( - actualList, - key=lambda k: self.moduleKey(k, subImports=True), - ) - if expectedList != actualList: - return (node, "I204", ", ".join(expectedList)) - - return None - - def sorted(self, toSort, key=None, reverse=False): - """ - Public method to sort the given list of names. - - @param toSort list of names to be sorted - @type list of str - @param key function to generate keys (defaults to None) - @type function (optional) - @param reverse flag indicating a reverse sort (defaults to False) - @type bool (optional) - @return sorted list of names - @rtype list of str - """ - return self.__sortingFunction(toSort, key=key, reverse=reverse) - - def __naturally(self, toSort, key=None, reverse=False): - """ - Private method to sort the given list of names naturally. - - Note: Natural sorting maintains the sort order of numbers (i.e. - [Q1, Q10, Q2] is sorted as [Q1, Q2, Q10] while the Python - standard sort would yield [Q1, Q10, Q2]. - - @param toSort list of names to be sorted - @type list of str - @param key function to generate keys (defaults to None) - @type function (optional) - @param reverse flag indicating a reverse sort (defaults to False) - @type bool (optional) - @return sorted list of names - @rtype list of str - """ - if key is None: - keyCallback = self.__naturalKeys - else: - - def keyCallback(text): - return self.__naturalKeys(key(text)) - - return sorted(toSort, key=keyCallback, reverse=reverse) - - def __atoi(self, text): - """ - Private method to convert the given text to an integer number. - - @param text text to be converted - @type str - @return integer number - @rtype int - """ - return int(text) if text.isdigit() else text - - def __naturalKeys(self, text): - """ - Private method to generate keys for natural sorting. - - @param text text to generate a key for - @type str - @return key for natural sorting - @rtype list of str or int - """ - return [self.__atoi(c) for c in re.split(r"(\d+)", text)] - - def moduleKey(self, moduleName, subImports=False): - """ - Public method to generate a key for the given module name. - - @param moduleName module name - @type str - @param subImports flag indicating a sub import like in - 'from foo import bar, baz' (defaults to False) - @type bool (optional) - @return generated key - @rtype str - """ - prefix = "" - - if subImports: - if moduleName.isupper() and len(moduleName) > 1: - prefix = "A" - elif moduleName[0:1].isupper(): - prefix = "B" - else: - prefix = "C" - if not self.__sortCaseSensitive: - moduleName = moduleName.lower() - - return f"{prefix}{moduleName}" - - ####################################################################### ## Tidy imports ## ## adapted from: flake8-tidy-imports v4.8.0