GeezerVison is showing github.com — fix: adapt to a 3.13 change in frame.f_lasti · coveragepy/coveragepy@f4c7a19
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: coverage/ctracer/tracer.c +4-1Lines changed: 4 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -710,7 +710,10 @@ CTracer_handle_return(CTracer *self, PyFrameObject *frame) | 710 | 710 | real_return = TRUE; | 711 | 711 | } | 712 | 712 | else { | 713 | | - real_return = (code_bytes[lasti + 2] != RESUME); | | 713 | +#if ENV_LASTI_IS_YIELD | | 714 | + lasti += 2; | | 715 | +#endif | | 716 | + real_return = (code_bytes[lasti] != RESUME); | 714 | 717 | } | 715 | 718 | #else | 716 | 719 | /* Need to distinguish between RETURN_VALUE and YIELD_VALUE. Read | |
Collapse file Copy file name to clipboardExpand all lines: coverage/ctracer/util.h +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 59 | 59 | #define MyCode_FreeCode(code) | 60 | 60 | #endif | 61 | 61 |
| | 62 | +// Where does frame.f_lasti point when yielding from a generator? | | 63 | +// It used to point at the YIELD, now it points at the RESUME. | | 64 | +// https://github.com/python/cpython/issues/113728 | | 65 | +#define ENV_LASTI_IS_YIELD (PY_VERSION_HEX < 0x030D0000) | | 66 | + | 62 | 67 | /* The values returned to indicate ok or error. */ | 63 | 68 | #define RET_OK 0 | 64 | 69 | #define RET_ERROR -1 | |
Collapse file Copy file name to clipboardExpand all lines: coverage/env.py +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -117,6 +117,11 @@ class PYBEHAVIOR: | 117 | 117 | # PEP669 Low Impact Monitoring: https://peps.python.org/pep-0669/ | 118 | 118 | pep669 = bool(getattr(sys, "monitoring", None)) | 119 | 119 |
| | 120 | + # Where does frame.f_lasti point when yielding from a generator? | | 121 | + # It used to point at the YIELD, now it points at the RESUME. | | 122 | + # https://github.com/python/cpython/issues/113728 | | 123 | + lasti_is_yield = (PYVERSION < (3, 13)) | | 124 | + | 120 | 125 |
| 121 | 126 | # Coverage.py specifics, about testing scenarios. See tests/testenv.py also. | 122 | 127 |
| |
Collapse file Copy file name to clipboardExpand all lines: coverage/pytracer.py +6-3Lines changed: 6 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 21 | 21 | ) | 22 | 22 |
| 23 | 23 | # We need the YIELD_VALUE opcode below, in a comparison-friendly form. | | 24 | +# PYVERSIONS: RESUME is new in Python3.11 | 24 | 25 | RESUME = dis.opmap.get("RESUME") | 25 | 26 | RETURN_VALUE = dis.opmap["RETURN_VALUE"] | 26 | 27 | if RESUME is None: | @@ -137,7 +138,7 @@ def _trace( | 137 | 138 | if THIS_FILE in frame.f_code.co_filename: | 138 | 139 | return None | 139 | 140 |
| 140 | | - #self.log(":", frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name + "()", event) | | 141 | + # self.log(":", frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name + "()", event) | 141 | 142 |
| 142 | 143 | if (self.stopped and sys.gettrace() == self._cached_bound_method_trace): # pylint: disable=comparison-with-callable | 143 | 144 | # The PyTrace.stop() method has been called, possibly by another | @@ -255,8 +256,10 @@ def _trace( | 255 | 256 | # A return from the end of a code object is a real return. | 256 | 257 | real_return = True | 257 | 258 | else: | 258 | | - # it's a real return. | 259 | | - real_return = (code[lasti + 2] != RESUME) | | 259 | + # It is a real return if we aren't going to resume next. | | 260 | + if env.PYBEHAVIOR.lasti_is_yield: | | 261 | + lasti += 2 | | 262 | + real_return = (code[lasti] != RESUME) | 260 | 263 | else: | 261 | 264 | if code[lasti] == RETURN_VALUE: | 262 | 265 | real_return = True | |
|