Skip to content

Commit 9ab9e0c

Browse files
committed
fix: 3.12 soft keyword type is bolded in HTML
1 parent 8624ce9 commit 9ab9e0c

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Unreleased
3232
- On Python 3.12+, we now disable SQLite writing journal files, which should be
3333
a little faster.
3434

35+
- The new 3.12 soft keyword ``type`` is properly bolded in HTML reports.
36+
3537
.. _issue 1605: https://github.com/nedbat/coveragepy/pull/1605
3638
.. _issue 1684: https://github.com/nedbat/coveragepy/issues/1684
3739
.. _pull 1685: https://github.com/nedbat/coveragepy/pull/1685

coverage/phystokens.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,25 @@ def _phys_tokens(toks: TokenInfos) -> TokenInfos:
7777
last_lineno = elineno
7878

7979

80-
class MatchCaseFinder(ast.NodeVisitor):
81-
"""Helper for finding match/case lines."""
80+
class SoftKeywordFinder(ast.NodeVisitor):
81+
"""Helper for finding lines with soft keywords, like match/case lines."""
8282
def __init__(self, source: str) -> None:
83-
# This will be the set of line numbers that start match or case statements.
84-
self.match_case_lines: Set[TLineNo] = set()
83+
# This will be the set of line numbers that start with a soft keyword.
84+
self.soft_key_lines: Set[TLineNo] = set()
8585
self.visit(ast.parse(source))
8686

8787
if sys.version_info >= (3, 10):
8888
def visit_Match(self, node: ast.Match) -> None:
8989
"""Invoked by ast.NodeVisitor.visit"""
90-
self.match_case_lines.add(node.lineno)
90+
self.soft_key_lines.add(node.lineno)
9191
for case in node.cases:
92-
self.match_case_lines.add(case.pattern.lineno)
92+
self.soft_key_lines.add(case.pattern.lineno)
93+
self.generic_visit(node)
94+
95+
if sys.version_info >= (3, 12):
96+
def visit_TypeAlias(self, node: ast.TypeAlias) -> None:
97+
"""Invoked by ast.NodeVisitor.visit"""
98+
self.soft_key_lines.add(node.lineno)
9399
self.generic_visit(node)
94100

95101

@@ -117,7 +123,7 @@ def source_token_lines(source: str) -> TSourceTokenLines:
117123
tokgen = generate_tokens(source)
118124

119125
if env.PYBEHAVIOR.soft_keywords:
120-
match_case_lines = MatchCaseFinder(source).match_case_lines
126+
soft_key_lines = SoftKeywordFinder(source).soft_key_lines
121127

122128
for ttype, ttext, (sline, scol), (_, ecol), _ in _phys_tokens(tokgen):
123129
mark_start = True
@@ -152,7 +158,7 @@ def source_token_lines(source: str) -> TSourceTokenLines:
152158
is_start_of_line = True
153159
else:
154160
is_start_of_line = False
155-
if is_start_of_line and sline in match_case_lines:
161+
if is_start_of_line and sline in soft_key_lines:
156162
tok_class = "key"
157163
line.append((tok_class, part))
158164
mark_end = True

tests/test_phystokens.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import os.path
99
import re
10+
import sys
1011
import textwrap
1112
import warnings
1213

@@ -118,7 +119,7 @@ class SoftKeywordTest(CoverageTest):
118119

119120
run_in_temp_dir = False
120121

121-
def test_soft_keywords(self) -> None:
122+
def test_soft_keywords_match_case(self) -> None:
122123
source = textwrap.dedent("""\
123124
match re.match(something):
124125
case ["what"]:
@@ -147,6 +148,16 @@ def match():
147148
assert tokens[10][2] == ("nam", "match")
148149
assert tokens[11][3] == ("nam", "case")
149150

151+
@pytest.mark.skipif(sys.version_info < (3, 12), reason="type is a soft keyword in 3.12")
152+
def test_soft_keyword_type(self) -> None:
153+
source = textwrap.dedent("""\
154+
type Point = tuple[float, float]
155+
type(int)
156+
""")
157+
tokens = list(source_token_lines(source))
158+
assert tokens[0][0] == ("key", "type")
159+
assert tokens[1][0] == ("nam", "type")
160+
150161

151162
# The default source file encoding.
152163
DEF_ENCODING = "utf-8"

0 commit comments

Comments
 (0)