src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/NameOrder/ImportNode.py

branch
eric7
changeset 10046
35b27af462ef
parent 9653
e67609152c5e
child 10439
21c28b0f9e41
equal deleted inserted replaced
10045:f5c57f8d17a4 10046:35b27af462ef
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2021 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class representing an import or import from node.
8 """
9
10 #
11 # adapted from flake8-alphabetize v0.0.21
12 #
13
14 import ast
15
16 from functools import total_ordering
17
18 from eric7.SystemUtilities import SysUtilities
19
20 from .ImportsEnums import GroupEnum, NodeTypeEnum
21
22
23 class ImportNodeError(Exception):
24 """
25 Class representing an exception for an invalid import node.
26 """
27
28 pass
29
30
31 @total_ordering
32 class ImportNode:
33 """
34 Class representing an import or import from node.
35 """
36
37 def __init__(self, appNames, astNode, checker, sortIgnoringStyle, sortFromFirst):
38 """
39 Constructor
40
41 @param appNames list of application package names
42 @type list of str
43 @param astNode reference to the ast node
44 @type ast.AST
45 @param checker reference to the checker object
46 @type ImportsChecker
47 @param sortIgnoringStyle flag indicating to sort ignoring the import style
48 @type bool
49 @param sortFromFirst flag indicating to sort from imports before straight ones
50 @type bool
51 @exception ImportNodeError raised to indicate an invalid node was
52 given to this class
53 """
54 if not isinstance(astNode, (ast.Import, ast.ImportFrom)):
55 raise ImportNodeError("Node type {0} not recognized".format(type(astNode)))
56
57 self.node = astNode
58 self.error = None
59 level = None
60 group = None
61
62 if isinstance(astNode, ast.Import):
63 self.nodeType = NodeTypeEnum.IMPORT
64 names = astNode.names
65
66 self.moduleName = names[0].name
67 self.asImport = bool(names[0].asname)
68 level = 0
69
70 elif isinstance(astNode, ast.ImportFrom):
71 module = astNode.module
72 self.moduleName = "" if module is None else module
73 self.nodeType = NodeTypeEnum.IMPORT_FROM
74
75 names = [n.name for n in astNode.names]
76 expectedNames = checker.sorted(
77 names,
78 key=lambda k: checker.moduleKey(k, subImports=True),
79 )
80 if names != expectedNames:
81 self.error = (self.node, "NO102", ", ".join(expectedNames))
82 level = astNode.level
83
84 self.asImport = any(n.asname for n in astNode.names)
85
86 if self.moduleName == "__future__":
87 group = GroupEnum.FUTURE
88 elif self.moduleName.split(".")[0] in SysUtilities.getStandardModules():
89 group = GroupEnum.STDLIB
90 elif level > 0:
91 group = GroupEnum.LOCALPATH
92 else:
93 group = GroupEnum.THIRDPARTY
94 for name in appNames:
95 if name == self.moduleName or self.moduleName.startswith(
96 "{0}.".format(name)
97 ):
98 group = GroupEnum.FIRSTPARTY
99 break
100
101 if group == GroupEnum.STDLIB:
102 self.sorter = (
103 (group, -self.nodeType, checker.moduleKey(self.moduleName))
104 if sortFromFirst
105 else (group, self.nodeType, checker.moduleKey(self.moduleName))
106 )
107 else:
108 m = self.moduleName
109 dotIndex = m.find(".")
110 topName = "." * level + (m if dotIndex == -1 else m[:dotIndex])
111 level = -level
112
113 if sortIgnoringStyle:
114 self.sorter = (
115 group,
116 level,
117 checker.moduleKey(topName),
118 self.nodeType,
119 m,
120 )
121 elif sortFromFirst:
122 self.sorter = (
123 group,
124 level,
125 -self.nodeType,
126 checker.moduleKey(topName),
127 m,
128 )
129 else:
130 self.sorter = (
131 group,
132 level,
133 self.nodeType,
134 checker.moduleKey(topName),
135 m,
136 )
137
138 def __eq__(self, other):
139 """
140 Special method implementing the equality operator.
141
142 @param other reference to the object to compare
143 @type ImportNode
144 @return flag indicating equality
145 @rtype bool
146 """
147 return self.sorter == other.sorter
148
149 def __lt__(self, other):
150 """
151 Special method implementing the less than operator.
152
153 @param other reference to the object to compare
154 @type ImportNode
155 @return flag indicating a less than situation
156 @rtype bool
157 """
158 return self.sorter < other.sorter
159
160 def __str__(self):
161 """
162 Special method to create a string representation of the instance.
163
164 @return string representation of the instance
165 @rtype str
166 @exception ImportNodeError raised to indicate an invalid node was
167 given to this class
168 """
169 if self.nodeType not in (NodeTypeEnum.IMPORT, NodeTypeEnum.IMPORT_FROM):
170 raise ImportNodeError(
171 "The node type {0} is not recognized.".format(self.nodeType)
172 )
173
174 if self.nodeType == NodeTypeEnum.IMPORT:
175 return "import {0}".format(self.moduleName)
176 elif self.nodeType == NodeTypeEnum.IMPORT_FROM:
177 level = self.node.level
178 levelStr = "" if level == 0 else "." * level
179 names = [
180 n.name + ("" if n.asname is None else " as {0}".format(n.asname))
181 for n in self.node.names
182 ]
183 return "from {0}{1} import {2}".format(
184 levelStr, self.moduleName, ", ".join(names)
185 )
186
187 return None

eric ide

mercurial