Skip to content

Commit 7b8dec9

Browse files
committed
feat!: remove fullcoverage, it doesn't work in 3.13
CPython stopped using it in python/cpython#88054
1 parent 1040bce commit 7b8dec9

File tree

8 files changed

+11
-125
lines changed

8 files changed

+11
-125
lines changed

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@ Unreleased
3434

3535
- The new 3.12 soft keyword ``type`` is properly bolded in HTML reports.
3636

37+
- Removed the "fullcoverage" feature used by CPython to measure the coverage of
38+
early-imported standard library modules. CPython `stopped using it
39+
<88054_>`_ in 2021, and it stopped working completely in Python 3.13.
40+
3741
.. _issue 1605: https://github.com/nedbat/coveragepy/pull/1605
3842
.. _issue 1684: https://github.com/nedbat/coveragepy/issues/1684
3943
.. _pull 1685: https://github.com/nedbat/coveragepy/pull/1685
44+
.. _88054: https://github.com/python/cpython/issues/88054
4045

4146

4247
.. scriv-start-here

MANIFEST.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ recursive-include lab *
3131
recursive-include .github *
3232

3333
recursive-include coverage *.pyi
34-
recursive-include coverage/fullcoverage *.py
3534
recursive-include coverage/ctracer *.c *.h
3635

3736
recursive-include doc *.py *.in *.pip *.rst *.txt *.png

coverage/collector.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from types import FrameType
1313
from typing import (
14-
cast, Any, Callable, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar,
14+
cast, Any, Callable, Dict, List, Mapping, Optional, Set, Type, TypeVar,
1515
)
1616

1717
from coverage import env
@@ -24,7 +24,7 @@
2424
from coverage.plugin import CoveragePlugin
2525
from coverage.pytracer import PyTracer
2626
from coverage.types import (
27-
TArc, TFileDisposition, TLineNo, TTraceData, TTraceFn, TTracer, TWarnFn,
27+
TArc, TFileDisposition, TTraceData, TTraceFn, TTracer, TWarnFn,
2828
)
2929

3030
os = isolate_module(os)
@@ -330,18 +330,9 @@ def start(self) -> None:
330330

331331
self.tracers = []
332332

333-
# Check to see whether we had a fullcoverage tracer installed. If so,
334-
# get the stack frames it stashed away for us.
335-
traces0: List[Tuple[Tuple[FrameType, str, Any], TLineNo]] = []
336-
fn0 = sys.gettrace()
337-
if fn0:
338-
tracer0 = getattr(fn0, '__self__', None)
339-
if tracer0:
340-
traces0 = getattr(tracer0, 'traces', [])
341-
342333
try:
343334
# Install the tracer on this thread.
344-
fn = self._start_tracer()
335+
self._start_tracer()
345336
except:
346337
if self._collectors:
347338
self._collectors[-1].resume()
@@ -351,13 +342,6 @@ def start(self) -> None:
351342
# stack of collectors.
352343
self._collectors.append(self)
353344

354-
# Replay all the events from fullcoverage into the new trace function.
355-
for (frame, event, arg), lineno in traces0:
356-
try:
357-
fn(frame, event, arg, lineno=lineno)
358-
except TypeError as ex:
359-
raise RuntimeError("fullcoverage must be run with the C trace function.") from ex
360-
361345
# Install our installation tracer in threading, to jump-start other
362346
# threads.
363347
if self.threading:

coverage/ctracer/tracer.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -857,24 +857,14 @@ CTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unuse
857857
* means it must be callable to be used in sys.settrace().
858858
*
859859
* So we make ourself callable, equivalent to invoking our trace function.
860-
*
861-
* To help with the process of replaying stored frames, this function has an
862-
* optional keyword argument:
863-
*
864-
* def CTracer_call(frame, event, arg, lineno=0)
865-
*
866-
* If provided, the lineno argument is used as the line number, and the
867-
* frame's f_lineno member is ignored.
868860
*/
869861
static PyObject *
870862
CTracer_call(CTracer *self, PyObject *args, PyObject *kwds)
871863
{
872864
PyFrameObject *frame;
873865
PyObject *what_str;
874866
PyObject *arg;
875-
int lineno = 0;
876867
int what;
877-
int orig_lineno;
878868
PyObject *ret = NULL;
879869
PyObject * ascii = NULL;
880870

@@ -888,10 +878,10 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds)
888878
NULL
889879
};
890880

891-
static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL};
881+
static char *kwlist[] = {"frame", "event", "arg", NULL};
892882

893883
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist,
894-
&PyFrame_Type, &frame, &PyUnicode_Type, &what_str, &arg, &lineno)) {
884+
&PyFrame_Type, &frame, &PyUnicode_Type, &what_str, &arg)) {
895885
goto done;
896886
}
897887

@@ -913,21 +903,12 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds)
913903
Py_DECREF(ascii);
914904
#endif
915905

916-
/* Save off the frame's lineno, and use the forced one, if provided. */
917-
orig_lineno = frame->f_lineno;
918-
if (lineno > 0) {
919-
frame->f_lineno = lineno;
920-
}
921-
922906
/* Invoke the C function, and return ourselves. */
923907
if (CTracer_trace(self, frame, what, arg) == RET_OK) {
924908
Py_INCREF(self);
925909
ret = (PyObject *)self;
926910
}
927911

928-
/* Clean up. */
929-
frame->f_lineno = orig_lineno;
930-
931912
/* For better speed, install ourselves the C way so that future calls go
932913
directly to CTracer_trace, without this intermediate function.
933914

coverage/fullcoverage/encodings.py

Lines changed: 0 additions & 57 deletions
This file was deleted.

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ warn_unused_configs = true
2626
warn_unused_ignores = true
2727

2828
exclude = """(?x)(
29-
^coverage/fullcoverage/encodings\\.py$ # can't import things into it.
30-
| ^tests/balance_xdist_plugin\\.py$ # not part of our test suite.
29+
^tests/balance_xdist_plugin\\.py$ # not part of our test suite.
3130
)"""
3231

3332
## PYLINT

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
package_data={
8888
'coverage': [
8989
'htmlfiles/*.*',
90-
'fullcoverage/*.*',
9190
'py.typed',
9291
]
9392
},

tests/test_process.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -556,30 +556,6 @@ def f():
556556
)
557557
assert msg in out
558558

559-
@pytest.mark.expensive
560-
@pytest.mark.skipif(not env.C_TRACER, reason="fullcoverage only works with the C tracer.")
561-
@pytest.mark.skipif(env.METACOV, reason="Can't test fullcoverage when measuring ourselves")
562-
def test_fullcoverage(self) -> None:
563-
# fullcoverage is a trick to get stdlib modules measured from
564-
# the very beginning of the process. Here we import os and
565-
# then check how many lines are measured.
566-
self.make_file("getenv.py", """\
567-
import os
568-
print("FOOEY == %s" % os.getenv("FOOEY"))
569-
""")
570-
571-
fullcov = os.path.join(os.path.dirname(coverage.__file__), "fullcoverage")
572-
self.set_environ("FOOEY", "BOO")
573-
self.set_environ("PYTHONPATH", fullcov)
574-
out = self.run_command("python -X frozen_modules=off -m coverage run -L getenv.py")
575-
assert out == "FOOEY == BOO\n"
576-
data = coverage.CoverageData()
577-
data.read()
578-
# The actual number of executed lines in os.py when it's
579-
# imported is 120 or so. Just running os.getenv executes
580-
# about 5.
581-
assert line_counts(data)['os.py'] > 50
582-
583559
# Pypy passes locally, but fails in CI? Perhaps the version of macOS is
584560
# significant? https://foss.heptapod.net/pypy/pypy/-/issues/3074
585561
@pytest.mark.skipif(env.PYPY, reason="PyPy is unreliable with this test")

0 commit comments

Comments
 (0)