@@ -52,52 +52,50 @@ def do_show_env():
5252 print (f" { env } = { os .environ [env ]!r} " )
5353
5454
55- def do_remove_extension ( * args ):
55+ def remove_extension ( core ):
5656 """Remove the compiled C extension, no matter what its name."""
5757
58+ if core == "ctrace" :
59+ return
60+
5861 so_patterns = """
5962 tracer.so
6063 tracer.*.so
6164 tracer.pyd
6265 tracer.*.pyd
6366 """ .split ()
6467
65- if "--from-install" in args :
66- # Get the install location using a subprocess to avoid
67- # locking the file we are about to delete
68- root = os .path .dirname (
69- subprocess .check_output (
70- [
71- sys .executable ,
72- "-Xutf8" ,
73- "-c" ,
74- "import coverage; print(coverage.__file__)" ,
75- ],
76- encoding = "utf-8" ,
77- ).strip (),
78- )
79- roots = [root ]
80- else :
81- roots = [
82- "coverage" ,
83- "build/*/coverage" ,
84- ".tox/*/[Ll]ib/*/site-packages/coverage" ,
85- ".tox/*/[Ll]ib/site-packages/coverage" ,
86- ]
68+ roots = [
69+ "coverage" ,
70+ "build/*/coverage" ,
71+ ".tox/*/[Ll]ib/*/site-packages/coverage" ,
72+ ".tox/*/[Ll]ib/site-packages/coverage" ,
73+ ]
8774
75+ # On windows at least, we can't delete a loaded .pyd file. So move them
76+ # out of the way into the tmp/ directory.
77+ os .makedirs ("tmp" , exist_ok = True )
8878 for root , pattern in itertools .product (roots , so_patterns ):
8979 pattern = os .path .join (root , pattern )
9080 if VERBOSITY > 1 :
9181 print (f"Searching for { pattern } from { os .getcwd ()} " )
9282 for filename in glob .glob (pattern ):
9383 if os .path .exists (filename ):
84+ hidden = f"tmp/{ os .path .basename (filename )} "
9485 if VERBOSITY > 1 :
95- print (f"Removing { os . path . abspath ( filename ) } " )
86+ print (f"Moving { filename } to { hidden } " )
9687 try :
97- os .remove (filename )
88+ if os .path .exists (hidden ):
89+ os .remove (hidden )
9890 except OSError as exc :
9991 if VERBOSITY > 1 :
100- print (f"Couldn't remove { os .path .abspath (filename )} : { exc } " )
92+ print (f"Couldn't remove { hidden } : { exc } " )
93+ else :
94+ try :
95+ os .rename (filename , hidden )
96+ except OSError as exc :
97+ if VERBOSITY > 1 :
98+ print (f"Couldn't rename: { exc } " )
10199
102100
103101def label_for_core (core ):
@@ -112,14 +110,17 @@ def label_for_core(core):
112110 raise ValueError (f"Bad core: { core !r} " )
113111
114112
115- def should_skip (core ):
113+ def should_skip (core , metacov ):
116114 """Is there a reason to skip these tests?
117115
118116 Return empty string to run tests, or a message about why we are skipping
119117 the tests.
120118 """
121119 skipper = ""
122120
121+ if metacov and core == "sysmon" and ((3 , 12 ) <= sys .version_info < (3 , 14 )):
122+ skipper = "sysmon can't measure branches in Python 3.12-3.13"
123+
123124 # $set_env.py: COVERAGE_TEST_CORES - List of cores to run: ctrace, pytrace, sysmon
124125 test_cores = os .getenv ("COVERAGE_TEST_CORES" )
125126 if test_cores :
@@ -140,7 +141,8 @@ def should_skip(core):
140141 skipper = f"No C core for { platform .python_implementation ()} "
141142
142143 if skipper :
143- return f"Skipping tests { label_for_core (core )} : { skipper } "
144+ what = "metacov" if metacov else "tests"
145+ return f"Skipping { what } { label_for_core (core )} : { skipper } "
144146 else :
145147 return ""
146148
@@ -157,10 +159,10 @@ def make_env_id(core):
157159
158160def run_tests (core , * runner_args ):
159161 """The actual running of tests."""
162+ remove_extension (core )
160163 if "COVERAGE_TESTING" not in os .environ :
161164 os .environ ["COVERAGE_TESTING" ] = "True"
162165 print_banner (label_for_core (core ))
163-
164166 return pytest .main (list (runner_args ))
165167
166168
@@ -209,6 +211,8 @@ def run_tests_with_coverage(core, *runner_args):
209211 if getattr (mod , "__file__" , "??" ).startswith (covdir ):
210212 covmods [name ] = mod
211213 del sys .modules [name ]
214+ remove_extension (core )
215+
212216 import coverage # pylint: disable=reimported
213217
214218 sys .modules .update (covmods )
@@ -246,15 +250,17 @@ def do_combine_html():
246250
247251def do_test_with_core (core , * runner_args ):
248252 """Run tests with a particular core."""
253+ metacov = os .getenv ("COVERAGE_COVERAGE" , "no" ) == "yes"
254+
249255 # If we should skip these tests, skip them.
250- skip_msg = should_skip (core )
256+ skip_msg = should_skip (core , metacov )
251257 if skip_msg :
252258 if VERBOSITY > 0 :
253259 print (skip_msg )
254260 return None
255261
256262 os .environ ["COVERAGE_CORE" ] = core
257- if os . getenv ( "COVERAGE_COVERAGE" , "no" ) == "yes" :
263+ if metacov :
258264 return run_tests_with_coverage (core , * runner_args )
259265 else :
260266 return run_tests (core , * runner_args )
0 commit comments