diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2021-10-27 08:51:43 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2021-10-27 09:12:30 -0400 |
commit | 055a9f4b38aebdabc8cb80dcc40a5b29b8f71781 (patch) | |
tree | 2ef5112132ccebdb9bb0e9553fddd8de8d20c93f | |
parent | 15aff0ad7d6c92851bc21fc39863a3949edbb9c6 (diff) | |
download | python-coveragepy-git-055a9f4b38aebdabc8cb80dcc40a5b29b8f71781.tar.gz |
fix(debug): ast_dump failed on a few things
-rw-r--r-- | coverage/parser.py | 7 | ||||
-rw-r--r-- | tests/stress_phystoken.tok | 10 | ||||
-rw-r--r-- | tests/test_parser.py | 37 | ||||
-rw-r--r-- | tests/test_phystokens.py | 6 |
4 files changed, 42 insertions, 18 deletions
diff --git a/coverage/parser.py b/coverage/parser.py index 80665b5a..ec788c06 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -1306,7 +1306,7 @@ def _is_simple_value(value): """Is `value` simple enough to be displayed on a single line?""" return ( value in [None, [], (), {}, set()] or - isinstance(value, (str, int, float)) + isinstance(value, (bytes, int, float, str)) ) def ast_dump(node, depth=0, print=print): # pylint: disable=redefined-builtin @@ -1352,7 +1352,10 @@ def ast_dump(node, depth=0, print=print): # pylint: disable=redefined-builtin elif isinstance(value, list): print(f"{prefix} [") for n in value: - ast_dump(n, depth + 8, print=print) + if _is_simple_value(n): + print(f"{next_indent} {n!r}") + else: + ast_dump(n, depth + 8, print=print) print(f"{next_indent}]") else: print(prefix) diff --git a/tests/stress_phystoken.tok b/tests/stress_phystoken.tok index f2b190c3..65ba45db 100644 --- a/tests/stress_phystoken.tok +++ b/tests/stress_phystoken.tok @@ -4,6 +4,7 @@ # Here's some random Python so that test_tokenize_myself will have some # stressful stuff to try. This file is .tok instead of .py so pylint won't # complain about it, check_eol won't look at it, etc. +# Some lines are here to reproduce fixed bugs in ast_dump also. first_back = """\ hey there! @@ -50,6 +51,15 @@ a_long_string = \ "3 is longer" def hello(): + global x # ast_dump bug print("Hello world!") hello() + +# ast dump bugs: +weird = { + **d, + **{'c': 7}, + 'd': 8, +} +self.hash.update(b'.') diff --git a/tests/test_parser.py b/tests/test_parser.py index ff7d9ef9..3197ffb4 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -4,7 +4,6 @@ """Tests for coverage.py's code parsing.""" import os.path -import re import textwrap import pytest @@ -14,7 +13,7 @@ from coverage.exceptions import NotPython from coverage.parser import ast_dump, ast_parse, PythonParser from tests.coveragetest import CoverageTest, TESTS_DIR -from tests.helpers import arcz_to_arcs +from tests.helpers import arcz_to_arcs, re_lines class PythonParserTest(CoverageTest): @@ -485,17 +484,23 @@ def test_ast_dump(): # Run the AST_DUMP code to make sure it doesn't fail, with some light # assertions. Use parser.py as the test code since it is the longest file, # and fitting, since it's the AST_DUMP code. - parser_py = os.path.join(TESTS_DIR, "../coverage/parser.py") - with open(parser_py) as f: - ast_root = ast_parse(f.read()) - result = [] - ast_dump(ast_root, print=result.append) - assert len(result) > 10000 - assert result[0] == "<Module" - assert result[-1] == ">" - - def count(pat): - return sum(1 for line in result if re.search(pat, line)) - - assert count(r"^\s+>") > 2000 - assert count(r"<Name @ \d+,\d+(:\d+)? id: '\w+'>") > 1000 + files = [ + os.path.join(TESTS_DIR, "../coverage/parser.py"), + os.path.join(TESTS_DIR, "stress_phystoken.tok"), + ] + for fname in files: + with open(fname) as f: + source = f.read() + num_lines = len(source.splitlines()) + print(f"file {fname} has {num_lines} lines") + ast_root = ast_parse(source) + result = [] + ast_dump(ast_root, print=result.append) + if num_lines < 100: + continue + assert len(result) > 5 * num_lines + assert result[0] == "<Module" + assert result[-1] == ">" + result_text = "\n".join(result) + assert len(re_lines(result_text, r"^\s+>")) > num_lines + assert len(re_lines(result_text, r"<Name @ \d+,\d+(:\d+)? id: '\w+'>")) > num_lines // 2 diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py index 3c214c63..fea581a5 100644 --- a/tests/test_phystokens.py +++ b/tests/test_phystokens.py @@ -15,6 +15,7 @@ from coverage.phystokens import neuter_encoding_declaration, compile_unicode from coverage.python import get_python_source from tests.coveragetest import CoverageTest, TESTS_DIR +from tests.helpers import re_lines # A simple program and its token stream. @@ -97,10 +98,15 @@ class PhysTokensTest(CoverageTest): def test_stress(self): # Check the tokenization of a stress-test file. + # And check that those files haven't been incorrectly "fixed". stress = os.path.join(TESTS_DIR, "stress_phystoken.tok") self.check_file_tokenization(stress) + with open(stress) as fstress: + assert re_lines(fstress.read(), r"\s$"), f"{stress} needs a trailing space." stress = os.path.join(TESTS_DIR, "stress_phystoken_dos.tok") self.check_file_tokenization(stress) + with open(stress) as fstress: + assert re_lines(fstress.read(), r"\s$"), f"{stress} needs a trailing space." @pytest.mark.skipif(not env.PYBEHAVIOR.soft_keywords, reason="Soft keywords are new in Python 3.10") |