30 |
30 |
31 # Opinionated |
31 # Opinionated |
32 "Y301", |
32 "Y301", |
33 ] |
33 ] |
34 |
34 |
35 def __init__(self, source, filename, selected, ignored, expected, repeat): |
35 def __init__(self, source, filename, tree, selected, ignored, expected, |
|
36 repeat): |
36 """ |
37 """ |
37 Constructor |
38 Constructor |
38 |
39 |
39 @param source source code to be checked |
40 @param source source code to be checked |
40 @type list of str |
41 @type list of str |
41 @param filename name of the source file |
42 @param filename name of the source file |
42 @type str |
43 @type str |
|
44 @param tree AST tree of the source code |
|
45 @type ast.Module |
43 @param selected list of selected codes |
46 @param selected list of selected codes |
44 @type list of str |
47 @type list of str |
45 @param ignored list of codes to be ignored |
48 @param ignored list of codes to be ignored |
46 @type list of str |
49 @type list of str |
47 @param expected list of expected codes |
50 @param expected list of expected codes |
53 self.__ignore = ('',) if selected else tuple(ignored) |
56 self.__ignore = ('',) if selected else tuple(ignored) |
54 self.__expected = expected[:] |
57 self.__expected = expected[:] |
55 self.__repeat = repeat |
58 self.__repeat = repeat |
56 self.__filename = filename |
59 self.__filename = filename |
57 self.__source = source[:] |
60 self.__source = source[:] |
|
61 self.__tree = copy.deepcopy(tree) |
58 |
62 |
59 # statistics counters |
63 # statistics counters |
60 self.counters = {} |
64 self.counters = {} |
61 |
65 |
62 # collection of detected errors |
66 # collection of detected errors |
112 "code": code, |
116 "code": code, |
113 "args": args, |
117 "args": args, |
114 } |
118 } |
115 ) |
119 ) |
116 |
120 |
117 def __reportInvalidSyntax(self): |
|
118 """ |
|
119 Private method to report a syntax error. |
|
120 """ |
|
121 exc_type, exc = sys.exc_info()[:2] |
|
122 if len(exc.args) > 1: |
|
123 offset = exc.args[1] |
|
124 if len(offset) > 2: |
|
125 offset = offset[1:3] |
|
126 else: |
|
127 offset = (1, 0) |
|
128 self.__error(offset[0] - 1, offset[1] or 0, |
|
129 'M901', exc_type.__name__, exc.args[0]) |
|
130 |
|
131 def __generateTree(self): |
|
132 """ |
|
133 Private method to generate an AST for our source. |
|
134 |
|
135 @return generated AST |
|
136 @rtype ast.AST |
|
137 """ |
|
138 return ast.parse("".join(self.__source), self.__filename) |
|
139 |
|
140 def run(self): |
121 def run(self): |
141 """ |
122 """ |
142 Public method to check the given source against functions |
123 Public method to check the given source against functions |
143 to be replaced by 'pathlib' equivalents. |
124 to be replaced by 'pathlib' equivalents. |
144 """ |
125 """ |
148 |
129 |
149 if not self.__checkCodes: |
130 if not self.__checkCodes: |
150 # don't do anything, if no codes were selected |
131 # don't do anything, if no codes were selected |
151 return |
132 return |
152 |
133 |
153 try: |
|
154 self.__tree = self.__generateTree() |
|
155 except (SyntaxError, TypeError): |
|
156 self.__reportInvalidSyntax() |
|
157 return |
|
158 |
|
159 # Add parent information |
134 # Add parent information |
160 for node in ast.walk(self.__tree): |
135 for node in ast.walk(self.__tree): |
161 for child in ast.iter_child_nodes(node): |
136 for child in ast.iter_child_nodes(node): |
162 child.parent = node # type: ignore |
137 child.parent = node # type: ignore |
163 |
138 |