64 # number table in the bytecode. |
64 # number table in the bytecode. |
65 self.raw_statements = set() |
65 self.raw_statements = set() |
66 |
66 |
67 # The raw line numbers of excluded lines of code, as marked by pragmas. |
67 # The raw line numbers of excluded lines of code, as marked by pragmas. |
68 self.raw_excluded = set() |
68 self.raw_excluded = set() |
|
69 |
|
70 # The line numbers of class definitions. |
|
71 self.raw_classdefs = set() |
69 |
72 |
70 # The line numbers of docstring lines. |
73 # The line numbers of docstring lines. |
71 self.raw_docstrings = set() |
74 self.raw_docstrings = set() |
72 |
75 |
73 # Internal detail, used by lab/parser.py. |
76 # Internal detail, used by lab/parser.py. |
128 )) |
131 )) |
129 if toktype == token.INDENT: |
132 if toktype == token.INDENT: |
130 indent += 1 |
133 indent += 1 |
131 elif toktype == token.DEDENT: |
134 elif toktype == token.DEDENT: |
132 indent -= 1 |
135 indent -= 1 |
|
136 elif toktype == token.NAME: |
|
137 if ttext == 'class': |
|
138 # Class definitions look like branches in the bytecode, so |
|
139 # we need to exclude them. The simplest way is to note the |
|
140 # lines with the 'class' keyword. |
|
141 self.raw_classdefs.add(slineno) |
133 elif toktype == token.OP: |
142 elif toktype == token.OP: |
134 if ttext == ':' and nesting == 0: |
143 if ttext == ':' and nesting == 0: |
135 should_exclude = (elineno in self.raw_excluded) or excluding_decorators |
144 should_exclude = (elineno in self.raw_excluded) or excluding_decorators |
136 if not excluding and should_exclude: |
145 if not excluding and should_exclude: |
137 # Start excluding a suite. We trigger off of the colon |
146 # Start excluding a suite. We trigger off of the colon |
290 if l2 in self.excluded: |
299 if l2 in self.excluded: |
291 # Arcs to excluded lines shouldn't count. |
300 # Arcs to excluded lines shouldn't count. |
292 continue |
301 continue |
293 exit_counts[l1] += 1 |
302 exit_counts[l1] += 1 |
294 |
303 |
|
304 # Class definitions have one extra exit, so remove one for each: |
|
305 for l in self.raw_classdefs: |
|
306 # Ensure key is there: class definitions can include excluded lines. |
|
307 if l in exit_counts: |
|
308 exit_counts[l] -= 1 |
|
309 |
295 return exit_counts |
310 return exit_counts |
296 |
311 |
297 def missing_arc_description(self, start, end, executed_arcs=None): |
312 def missing_arc_description(self, start, end, executed_arcs=None): |
298 """Provide an English sentence describing a missing arc.""" |
313 """Provide an English sentence describing a missing arc.""" |
299 if self._missing_arc_fragments is None: |
314 if self._missing_arc_fragments is None: |
1285 start = self.line_for_node(node) |
1300 start = self.line_for_node(node) |
1286 self.add_arc(-start, start, None, f"didn't run the {noun} on line {start}") |
1301 self.add_arc(-start, start, None, f"didn't run the {noun} on line {start}") |
1287 self.add_arc(start, -start, None, f"didn't finish the {noun} on line {start}") |
1302 self.add_arc(start, -start, None, f"didn't finish the {noun} on line {start}") |
1288 return _code_object__expression_callable |
1303 return _code_object__expression_callable |
1289 |
1304 |
1290 # pylint: disable=too-many-function-args |
|
1291 _code_object__Lambda = _make_expression_code_method("lambda") |
1305 _code_object__Lambda = _make_expression_code_method("lambda") |
1292 _code_object__GeneratorExp = _make_expression_code_method("generator expression") |
1306 _code_object__GeneratorExp = _make_expression_code_method("generator expression") |
1293 _code_object__DictComp = _make_expression_code_method("dictionary comprehension") |
1307 _code_object__DictComp = _make_expression_code_method("dictionary comprehension") |
1294 _code_object__SetComp = _make_expression_code_method("set comprehension") |
1308 _code_object__SetComp = _make_expression_code_method("set comprehension") |
1295 _code_object__ListComp = _make_expression_code_method("list comprehension") |
1309 _code_object__ListComp = _make_expression_code_method("list comprehension") |