30 ## Annotation Coverage |
30 ## Annotation Coverage |
31 "A881", |
31 "A881", |
32 |
32 |
33 ## Annotation Complexity |
33 ## Annotation Complexity |
34 "A891", |
34 "A891", |
35 |
|
36 ## Syntax Error |
|
37 "A999", |
|
38 ] |
35 ] |
39 |
36 |
40 def __init__(self, source, filename, select, ignore, expected, repeat, |
37 def __init__(self, source, filename, tree, select, ignore, expected, repeat, |
41 args): |
38 args): |
42 """ |
39 """ |
43 Constructor |
40 Constructor |
44 |
41 |
45 @param source source code to be checked |
42 @param source source code to be checked |
46 @type list of str |
43 @type list of str |
47 @param filename name of the source file |
44 @param filename name of the source file |
48 @type str |
45 @type str |
|
46 @param tree AST tree of the source code |
|
47 @type ast.Module |
49 @param select list of selected codes |
48 @param select list of selected codes |
50 @type list of str |
49 @type list of str |
51 @param ignore list of codes to be ignored |
50 @param ignore list of codes to be ignored |
52 @type list of str |
51 @type list of str |
53 @param expected list of expected codes |
52 @param expected list of expected codes |
61 self.__ignore = ('',) if select else tuple(ignore) |
60 self.__ignore = ('',) if select else tuple(ignore) |
62 self.__expected = expected[:] |
61 self.__expected = expected[:] |
63 self.__repeat = repeat |
62 self.__repeat = repeat |
64 self.__filename = filename |
63 self.__filename = filename |
65 self.__source = source[:] |
64 self.__source = source[:] |
|
65 self.__tree = copy.deepcopy(tree) |
66 self.__args = args |
66 self.__args = args |
67 |
67 |
68 # statistics counters |
68 # statistics counters |
69 self.counters = {} |
69 self.counters = {} |
70 |
70 |
139 "code": code, |
139 "code": code, |
140 "args": args, |
140 "args": args, |
141 } |
141 } |
142 ) |
142 ) |
143 |
143 |
144 def __reportInvalidSyntax(self): |
|
145 """ |
|
146 Private method to report a syntax error. |
|
147 """ |
|
148 exc_type, exc = sys.exc_info()[:2] |
|
149 if len(exc.args) > 1: |
|
150 offset = exc.args[1] |
|
151 if len(offset) > 2: |
|
152 offset = offset[1:3] |
|
153 else: |
|
154 offset = (1, 0) |
|
155 self.__error(offset[0] - 1, offset[1] or 0, |
|
156 'A999', exc_type.__name__, exc.args[0]) |
|
157 |
|
158 def __generateTree(self): |
|
159 """ |
|
160 Private method to generate an AST for our source. |
|
161 |
|
162 @return generated AST |
|
163 @rtype ast.Module |
|
164 """ |
|
165 return ast.parse("".join(self.__source), self.__filename) |
|
166 |
|
167 def run(self): |
144 def run(self): |
168 """ |
145 """ |
169 Public method to check the given source against annotation issues. |
146 Public method to check the given source against annotation issues. |
170 """ |
147 """ |
171 if not self.__filename: |
148 if not self.__filename: |
172 # don't do anything, if essential data is missing |
149 # don't do anything, if essential data is missing |
173 return |
150 return |
174 |
151 |
175 if not self.__checkers: |
152 if not self.__checkers: |
176 # don't do anything, if no codes were selected |
153 # don't do anything, if no codes were selected |
177 return |
|
178 |
|
179 try: |
|
180 self.__tree = self.__generateTree() |
|
181 except (SyntaxError, TypeError): |
|
182 self.__reportInvalidSyntax() |
|
183 return |
154 return |
184 |
155 |
185 for check in self.__checkers: |
156 for check in self.__checkers: |
186 check() |
157 check() |
187 |
158 |