--- a/eric6/DebugClients/Python/coverage/parser.py Wed Feb 19 19:38:36 2020 +0100 +++ b/eric6/DebugClients/Python/coverage/parser.py Sat Feb 22 14:27:42 2020 +0100 @@ -1,5 +1,5 @@ # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt +# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt """Code parsing for coverage.py.""" @@ -13,7 +13,7 @@ from coverage import env from coverage.backward import range # pylint: disable=redefined-builtin from coverage.backward import bytes_to_ints, string_class -from coverage.bytecode import CodeObjects +from coverage.bytecode import code_objects from coverage.debug import short_stack from coverage.misc import contract, join_regex, new_contract, nice_pair, one_of from coverage.misc import NoSource, NotPython, StopEverything @@ -207,7 +207,11 @@ def first_line(self, line): """Return the first line number of the statement including `line`.""" - return self._multiline.get(line, line) + if line < 0: + line = -self._multiline.get(-line, -line) + else: + line = self._multiline.get(line, line) + return line def first_lines(self, lines): """Map the line numbers in `lines` to the correct first line of the @@ -383,8 +387,7 @@ The iteration includes `self` as its first value. """ - children = CodeObjects(self.code) - return (ByteParser(self.text, code=c) for c in children) + return (ByteParser(self.text, code=c) for c in code_objects(self.code)) def _bytes_lines(self): """Map byte offsets to line numbers in `code`. @@ -409,7 +412,7 @@ yield (byte_num, line_num) last_line_num = line_num byte_num += byte_incr - if env.PYVERSION >= (3, 6) and line_incr >= 0x80: + if env.PYBEHAVIOR.negative_lnotab and line_incr >= 0x80: line_incr -= 0x100 line_num += line_incr if line_num != last_line_num: @@ -491,6 +494,7 @@ # Turn on AST dumps with an environment variable. +# $set_env.py: COVERAGE_AST_DUMP - Dump the AST nodes when parsing code. AST_DUMP = bool(int(os.environ.get("COVERAGE_AST_DUMP", 0))) class NodeList(object): @@ -521,8 +525,8 @@ if AST_DUMP: # pragma: debugging # Dump the AST so that failing tests have helpful output. - print("Statements: {0}".format(self.statements)) - print("Multiline map: {0}".format(self.multiline)) + print("Statements: {}".format(self.statements)) + print("Multiline map: {}".format(self.multiline)) ast_dump(self.root_node) self.arcs = set() @@ -535,6 +539,7 @@ self.missing_arc_fragments = collections.defaultdict(list) self.block_stack = [] + # $set_env.py: COVERAGE_TRACK_ARCS - Trace every arc added while parsing code. self.debug = bool(int(os.environ.get("COVERAGE_TRACK_ARCS", 0))) def analyze(self): @@ -652,7 +657,7 @@ # to see if it's overlooked. if 0: if node_name not in self.OK_TO_DEFAULT: - print("*** Unhandled: {0}".format(node)) + print("*** Unhandled: {}".format(node)) # Default for simple statements: one exit from this node. return set([ArcStart(self.line_for_node(node))]) @@ -822,7 +827,7 @@ for xit in exits: self.add_arc( xit.lineno, -block.start, xit.cause, - "didn't except from function '{0}'".format(block.name), + "didn't except from function {!r}".format(block.name), ) break @@ -837,7 +842,7 @@ for xit in exits: self.add_arc( xit.lineno, -block.start, xit.cause, - "didn't return from function '{0}'".format(block.name), + "didn't return from function {!r}".format(block.name), ) break @@ -1160,17 +1165,17 @@ for xit in exits: self.add_arc( xit.lineno, -start, xit.cause, - "didn't exit the body of class '{0}'".format(node.name), + "didn't exit the body of class {!r}".format(node.name), ) def _make_oneline_code_method(noun): # pylint: disable=no-self-argument """A function to make methods for online callable _code_object__ methods.""" def _code_object__oneline_callable(self, node): start = self.line_for_node(node) - self.add_arc(-start, start, None, "didn't run the {0} on line {1}".format(noun, start)) + self.add_arc(-start, start, None, "didn't run the {} on line {}".format(noun, start)) self.add_arc( start, -start, None, - "didn't finish the {0} on line {1}".format(noun, start), + "didn't finish the {} on line {}".format(noun, start), ) return _code_object__oneline_callable @@ -1202,15 +1207,15 @@ """ indent = " " * depth if not isinstance(node, ast.AST): - print("{0}<{1} {2!r}>".format(indent, node.__class__.__name__, node)) + print("{}<{} {!r}>".format(indent, node.__class__.__name__, node)) return lineno = getattr(node, "lineno", None) if lineno is not None: - linemark = " @ {0}".format(node.lineno) + linemark = " @ {}".format(node.lineno) else: linemark = "" - head = "{0}<{1}{2}".format(indent, node.__class__.__name__, linemark) + head = "{}<{}{}".format(indent, node.__class__.__name__, linemark) named_fields = [ (name, value) @@ -1218,28 +1223,28 @@ if name not in SKIP_DUMP_FIELDS ] if not named_fields: - print("{0}>".format(head)) + print("{}>".format(head)) elif len(named_fields) == 1 and _is_simple_value(named_fields[0][1]): field_name, value = named_fields[0] - print("{0} {1}: {2!r}>".format(head, field_name, value)) + print("{} {}: {!r}>".format(head, field_name, value)) else: print(head) if 0: - print("{0}# mro: {1}".format( + print("{}# mro: {}".format( indent, ", ".join(c.__name__ for c in node.__class__.__mro__[1:]), )) next_indent = indent + " " for field_name, value in named_fields: - prefix = "{0}{1}:".format(next_indent, field_name) + prefix = "{}{}:".format(next_indent, field_name) if _is_simple_value(value): - print("{0} {1!r}".format(prefix, value)) + print("{} {!r}".format(prefix, value)) elif isinstance(value, list): - print("{0} [".format(prefix)) + print("{} [".format(prefix)) for n in value: ast_dump(n, depth + 8) - print("{0}]".format(next_indent)) + print("{}]".format(next_indent)) else: print(prefix) ast_dump(value, depth + 8) - print("{0}>".format(indent)) + print("{}>".format(indent))