Coverage for tests / test_context.py: 100.000%
174 statements
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-29 20:34 +0000
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-29 20:34 +0000
1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
4"""Tests for context support."""
6from __future__ import annotations 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
8import inspect 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
9import os.path 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
11from typing import Any 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
12from unittest import mock 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
14import pytest 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
16import coverage 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
17from coverage.context import qualname_from_frame 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
18from coverage.data import CoverageData, sorted_lines 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
19from coverage.types import TArc, TCovKwargs, TLineNo 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
21from tests import testenv 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
22from tests.coveragetest import CoverageTest 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
23from tests.helpers import assert_count_equal 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
26class StaticContextTest(CoverageTest): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
27 """Tests of the static context."""
29 def test_no_context(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
30 self.make_file("main.py", "a = 1") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
31 cov = coverage.Coverage() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
32 self.start_import_stop(cov, "main") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
33 data = cov.get_data() 1abcdXefghijklmnopqrs0tuvwxyzABCDEFGHIJKLMNOPQRSTUVW
34 assert_count_equal(data.measured_contexts(), [""]) 1abcdXefghijklmnopqrs0tuvwxyzABCDEFGHIJKLMNOPQRSTUVW
36 def test_static_context(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
37 self.make_file("main.py", "a = 1") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
38 cov = coverage.Coverage(context="gooey") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
39 self.start_import_stop(cov, "main") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
40 data = cov.get_data() 1abcdefghiYjklmnZopqrstuvwxyzABCD1EFGHI3JKLMNOPQRS4TUVW
41 assert_count_equal(data.measured_contexts(), ["gooey"]) 1abcdefghiYjklmnZopqrstuvwxyzABCD1EFGHI3JKLMNOPQRS4TUVW
43 SOURCE = """\ 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
44 a = 1
45 if a > 2:
46 a = 3
47 assert a == 1
48 """
50 LINES = [1, 2, 4] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
52 def run_red_blue(self, **options: TCovKwargs) -> tuple[CoverageData, CoverageData]: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
53 """Run red.py and blue.py, and return their CoverageData objects."""
54 self.make_file("red.py", self.SOURCE) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
55 red_cov = coverage.Coverage(context="red", data_suffix="r", source=["."], **options) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
56 self.start_import_stop(red_cov, "red") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
57 red_cov.save() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
58 red_data = red_cov.get_data() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
60 self.make_file("blue.py", self.SOURCE) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
61 blue_cov = coverage.Coverage(context="blue", data_suffix="b", source=["."], **options) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
62 self.start_import_stop(blue_cov, "blue") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
63 blue_cov.save() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
64 blue_data = blue_cov.get_data() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
66 return red_data, blue_data 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
68 def test_combining_line_contexts(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
69 red_data, blue_data = self.run_red_blue() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
70 for datas in [[red_data, blue_data], [blue_data, red_data]]: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
71 combined = CoverageData(suffix="combined") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
72 for data in datas: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
73 combined.update(data) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
75 assert combined.measured_contexts() == {"red", "blue"} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
77 full_names = {os.path.basename(f): f for f in combined.measured_files()} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
78 assert_count_equal(full_names, ["red.py", "blue.py"]) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
80 fred = full_names["red.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
81 fblue = full_names["blue.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
83 def assert_combined_lines(filename: str, context: str, lines: list[TLineNo]) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
84 # pylint: disable=cell-var-from-loop
85 combined.set_query_context(context) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
86 assert combined.lines(filename) == lines 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
88 assert_combined_lines(fred, "red", self.LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
89 assert_combined_lines(fred, "blue", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
90 assert_combined_lines(fblue, "red", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
91 assert_combined_lines(fblue, "blue", self.LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHIJKLMN2OPQRSTUVW
93 def test_combining_arc_contexts(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
94 red_data, blue_data = self.run_red_blue(branch=True) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
96 # The exact arc data changes depending on the core and the version.
97 # Extract the red arc data for comparisons below.
98 arc_data = red_data.arcs( 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
99 next(fname for fname in red_data.measured_files() if "red.py" in fname)
100 )
101 assert arc_data is not None 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
103 for datas in [[red_data, blue_data], [blue_data, red_data]]: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
104 combined = CoverageData(suffix="combined") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
105 for data in datas: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
106 combined.update(data) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
108 assert combined.measured_contexts() == {"red", "blue"} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
110 full_names = {os.path.basename(f): f for f in combined.measured_files()} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
111 assert_count_equal(full_names, ["red.py", "blue.py"]) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
113 fred = full_names["red.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
114 fblue = full_names["blue.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
116 def assert_combined_lines(filename: str, context: str, lines: list[TLineNo]) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
117 # pylint: disable=cell-var-from-loop
118 combined.set_query_context(context) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
119 assert combined.lines(filename) == lines 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
121 assert_combined_lines(fred, "red", self.LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
122 assert_combined_lines(fred, "blue", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
123 assert_combined_lines(fblue, "red", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
124 assert_combined_lines(fblue, "blue", self.LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
126 def assert_combined_arcs(filename: str, context: str, lines: list[TArc]) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
127 # pylint: disable=cell-var-from-loop
128 combined.set_query_context(context) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
129 assert combined.arcs(filename) == lines 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
131 assert_combined_arcs(fred, "red", arc_data) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
132 assert_combined_arcs(fred, "blue", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
133 assert_combined_arcs(fblue, "red", []) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
134 assert_combined_arcs(fblue, "blue", arc_data) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
137@pytest.mark.skipif(not testenv.DYN_CONTEXTS, reason="No dynamic contexts with this core") 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
138class DynamicContextTest(CoverageTest): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
139 """Tests of dynamically changing contexts."""
141 SOURCE = """\ 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
142 def helper(lineno):
143 x = 2
145 def test_one():
146 a = 5
147 helper(6)
149 def test_two():
150 a = 9
151 b = 10
152 if a > 11:
153 b = 12
154 assert a == (13-4)
155 assert b == (14-4)
156 helper(15)
158 test_one()
159 x = 18
160 helper(19)
161 test_two()
162 """
164 OUTER_LINES = [1, 4, 8, 17, 18, 19, 2, 20] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
165 TEST_ONE_LINES = [5, 6, 2] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
166 TEST_TWO_LINES = [9, 10, 11, 13, 14, 15, 2] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
168 def test_dynamic_alone(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
169 self.make_file("two_tests.py", self.SOURCE) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
170 cov = coverage.Coverage(source=["."]) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
171 cov.set_option("run:dynamic_context", "test_function") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
172 self.start_import_stop(cov, "two_tests") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
173 data = cov.get_data() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
175 full_names = {os.path.basename(f): f for f in data.measured_files()} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
176 fname = full_names["two_tests.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
177 assert_count_equal( 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
178 data.measured_contexts(),
179 ["", "two_tests.test_one", "two_tests.test_two"],
180 )
182 def assert_context_lines(context: str, lines: list[TLineNo]) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
183 data.set_query_context(context) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
184 assert_count_equal(lines, sorted_lines(data, fname)) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
186 assert_context_lines("", self.OUTER_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
187 assert_context_lines("two_tests.test_one", self.TEST_ONE_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
188 assert_context_lines("two_tests.test_two", self.TEST_TWO_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
190 def test_static_and_dynamic(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
191 self.make_file("two_tests.py", self.SOURCE) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
192 cov = coverage.Coverage(context="stat", source=["."]) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
193 cov.set_option("run:dynamic_context", "test_function") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
194 self.start_import_stop(cov, "two_tests") 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
195 data = cov.get_data() 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
197 full_names = {os.path.basename(f): f for f in data.measured_files()} 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
198 fname = full_names["two_tests.py"] 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
199 assert_count_equal( 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
200 data.measured_contexts(),
201 ["stat", "stat|two_tests.test_one", "stat|two_tests.test_two"],
202 )
204 def assert_context_lines(context: str, lines: list[TLineNo]) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
205 data.set_query_context(context) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
206 assert_count_equal(lines, sorted_lines(data, fname)) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
208 assert_context_lines("stat", self.OUTER_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
209 assert_context_lines("stat|two_tests.test_one", self.TEST_ONE_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
210 assert_context_lines("stat|two_tests.test_two", self.TEST_TWO_LINES) 1abcdXefghiYjklmnZopqrs0tuvwxyzABCD1EFGHI3JKLMN2OPQRS4TUVW
213def get_qualname() -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
214 """Helper to return qualname_from_frame for the caller."""
215 stack = inspect.stack()[1:] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
216 if any(sinfo[0].f_code.co_name == "get_qualname" for sinfo in stack): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
217 # We're calling ourselves recursively, maybe because we're testing
218 # properties. Return an int to try to get back on track.
219 return 17 # type: ignore[return-value] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
220 caller_frame = stack[0][0] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
221 return qualname_from_frame(caller_frame) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
224# pylint: disable=missing-class-docstring, missing-function-docstring, unused-argument
227class Parent: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
228 def meth(self) -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
229 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
231 @property 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
232 def a_property(self) -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
233 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
236class Child(Parent): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
237 pass 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
240class SomethingElse: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
241 pass 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
244class MultiChild(SomethingElse, Child): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
245 pass 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
248def no_arguments() -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
249 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
252def plain_old_function(a: Any, b: Any) -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
253 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
256def fake_out(self: Any) -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
257 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
260def patch_meth(self: Any) -> str | None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
261 return get_qualname() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
264# pylint: enable=missing-class-docstring, missing-function-docstring, unused-argument
267class QualnameTest(CoverageTest): 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
268 """Tests of qualname_from_frame."""
270 # Pylint gets confused about meth() below.
271 # pylint: disable=no-value-for-parameter
273 run_in_temp_dir = False 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
275 def test_method(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
276 assert Parent().meth() == "tests.test_context.Parent.meth" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
278 def test_inherited_method(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
279 assert Child().meth() == "tests.test_context.Parent.meth" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
281 def test_mi_inherited_method(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
282 assert MultiChild().meth() == "tests.test_context.Parent.meth" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
284 def test_no_arguments(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
285 assert no_arguments() == "tests.test_context.no_arguments" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
287 def test_plain_old_function(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
288 assert plain_old_function(0, 1) == "tests.test_context.plain_old_function" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
290 def test_fake_out(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
291 assert fake_out(0) == "tests.test_context.fake_out" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
293 def test_property(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
294 assert Parent().a_property == "tests.test_context.Parent.a_property" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
296 def test_changeling(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
297 c = Child() 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
298 c.meth = patch_meth # type: ignore[assignment] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
299 assert c.meth(c) == "tests.test_context.patch_meth" # type: ignore[call-arg] 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
301 def test_bug_829(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
302 # A class with a name like a function shouldn't confuse qualname_from_frame.
303 class test_something: # pylint: disable=unused-variable 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
304 assert get_qualname() is None 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
306 def test_bug_1210(self) -> None: 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
307 # Under pyarmor (an obfuscator), a function can have a "self" argument,
308 # but then not have a "self" local.
309 co = mock.Mock(co_name="a_co_name", co_argcount=1, co_varnames=["self"]) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
310 frame = mock.Mock(f_code=co, f_locals={}) 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW
311 assert qualname_from_frame(frame) == "unittest.mock.a_co_name" 1abcdXefghiYjklmnZopqrs0tuvwxyzAB5CD61E7FG8HI93J!KL#MN$2O%PQ'RS(4T)UVW