Skip to content

Commit e1c6667

Browse files
committed
Add some shims from the FrameType/PyFrameObject* typechecks. Replace some type castings with some others. The Event doesn't need a Tracer instance anymore.
1 parent 403cf02 commit e1c6667

4 files changed

Lines changed: 38 additions & 42 deletions

File tree

src/hunter/_event.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# cython: language_level=3str
21
cimport cython
32

43
from ._tracer cimport *
@@ -9,6 +8,7 @@ cdef extern from *:
98

109

1110
@cython.final
11+
@cython.auto_pickle(False)
1212
cdef class Event:
1313
cdef:
1414
readonly FrameType frame

src/hunter/_event.pyx

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,11 @@ from tokenize import generate_tokens
1111

1212
from cpython.pythread cimport PyThread_get_thread_ident
1313
from cpython.ref cimport PyObject
14-
from cython cimport auto_pickle
15-
16-
from ._tracer cimport Tracer
1714

1815
from .const import SITE_PACKAGES_PATHS
1916
from .const import SYS_PREFIX_PATHS
2017
from .util import CYTHON_SUFFIX_RE
2118
from .util import LEADING_WHITESPACE_RE
22-
from .util import MISSING
2319
from .util import get_func_in_mro
2420
from .util import get_main_thread
2521
from .util import if_same_code
@@ -45,7 +41,6 @@ cdef const PyObject** KIND_NAMES = [
4541
]
4642

4743

48-
@auto_pickle(False)
4944
cdef class Event:
5045
"""
5146
A wrapper object for Frame objects. Instances of this are passed to your custom functions or predicates.
@@ -57,23 +52,8 @@ cdef class Event:
5752
kind (str): A string like ``'call'``, ``'line'``, ``'return'`` or ``'exception'``.
5853
arg: A value that depends on ``kind``. Usually is ``None`` but for ``'return'`` or ``'exception'`` other values
5954
may be expected.
60-
tracer (:class:`hunter.tracer.Tracer`): The :class:`~hunter.tracer.Tracer` instance that created the event.
61-
Needed for the ``calls`` and ``depth`` fields.
6255
"""
63-
def __init__(self, FrameType frame, int kind, object arg, Tracer tracer=None, object depth=None, object calls=None,
64-
object threading_support=MISSING):
65-
if tracer is None:
66-
if depth is None:
67-
raise TypeError('Missing argument: depth (required because tracer was not given).')
68-
if calls is None:
69-
raise TypeError('Missing argument: calls (required because tracer was not given).')
70-
if threading_support is MISSING:
71-
raise TypeError('Missing argument: threading_support (required because tracer was not given).')
72-
else:
73-
depth = tracer.depth
74-
calls = tracer.calls
75-
threading_support = tracer.threading_support
76-
56+
def __init__(self, FrameType frame, int kind, object arg, int depth, int calls, bint threading_support):
7757
self.arg = arg
7858
self.frame = frame
7959
self.kind = <str> KIND_NAMES[kind]
@@ -117,7 +97,7 @@ cdef class Event:
11797
cdef int position
11898

11999
if self._instruction is UNSET:
120-
position = PyFrame_GetLasti(<PyFrameObject*> self.frame)
100+
position = Hunter_PyFrame_GetLasti(self.frame)
121101
co_code = PyCode_GetCode(self.code_getter())
122102
if co_code and position >= 0:
123103
self._instruction = co_code[position]
@@ -161,7 +141,7 @@ cdef class Event:
161141
if self.builtin:
162142
self._locals = {}
163143
else:
164-
self._locals = PyFrame_GetLocals(<PyFrameObject*> self.frame)
144+
self._locals = Hunter_PyFrame_GetLocals(self.frame)
165145
return self._locals
166146

167147
@property
@@ -173,7 +153,7 @@ cdef class Event:
173153
if self.builtin:
174154
self._locals = {}
175155
else:
176-
self._globals = PyFrame_GetGlobals(<PyFrameObject*> self.frame)
156+
self._globals = Hunter_PyFrame_GetGlobals(self.frame)
177157
return self._globals
178158

179159
@property
@@ -266,7 +246,7 @@ cdef class Event:
266246

267247
cdef inline lineno_getter(self):
268248
if self._lineno is UNSET:
269-
self._lineno = PyFrame_GetLineNumber(<PyFrameObject*> self.frame)
249+
self._lineno = Hunter_PyFrame_GetLineNumber(self.frame)
270250
return self._lineno
271251

272252
@property
@@ -275,7 +255,7 @@ cdef class Event:
275255

276256
cdef inline CodeType code_getter(self):
277257
if self._code is UNSET:
278-
return PyFrame_GetCode(<PyFrameObject*> self.frame)
258+
return Hunter_PyFrame_GetCode(self.frame)
279259
else:
280260
return self._code
281261

src/hunter/_tracer.pxd

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,31 @@ from cpython.ref cimport PyObject
77
ctypedef extern FrameType
88

99
cdef extern from "vendor/_compat.h":
10-
CodeType PyFrame_GetCode(PyFrameObject *frame)
11-
int PyFrame_GetLasti(PyFrameObject *frame)
10+
"""
11+
static inline PyCodeObject* Hunter_PyFrame_GetCode(PyObject* frame) {
12+
return PyFrame_GetCode((PyFrameObject*) frame);
13+
}
14+
static inline int Hunter_PyFrame_GetLasti(PyObject* frame) {
15+
return PyFrame_GetLasti((PyFrameObject*) frame);
16+
}
17+
static inline int Hunter_PyFrame_GetLineNumber(PyObject* frame) {
18+
return PyFrame_GetLineNumber((PyFrameObject*) frame);
19+
}
20+
static inline PyObject* Hunter_PyFrame_GetGlobals(PyObject* frame) {
21+
return PyFrame_GetGlobals((PyFrameObject*) frame);
22+
}
23+
static inline PyObject* Hunter_PyFrame_GetLocals(PyObject* frame) {
24+
return PyFrame_GetLocals((PyFrameObject*) frame);
25+
}
26+
"""
1227
object PyCode_GetCode(CodeType)
1328
object PyCode_GetVarnames(CodeType)
14-
object PyFrame_GetGlobals(PyFrameObject *frame)
15-
object PyFrame_GetLocals(PyFrameObject *frame)
29+
CodeType Hunter_PyFrame_GetCode(FrameType frame)
30+
int Hunter_PyFrame_GetLasti(FrameType frame)
31+
int Hunter_PyFrame_GetLineNumber(FrameType frame)
32+
object Hunter_PyFrame_GetGlobals(FrameType frame)
33+
object Hunter_PyFrame_GetLocals(FrameType frame)
34+
1635

1736
cdef extern from *:
1837
void PyEval_SetTrace(Py_tracefunc, PyObject*)

src/hunter/_tracer.pyx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
import threading
33
import traceback
44

5-
from cpython cimport pystate
65
from cpython.pystate cimport PyThreadState_Get
7-
86
from ._event cimport Event
97
from ._predicates cimport fast_call
108

@@ -22,9 +20,8 @@ cdef dict KIND_INTS = {
2220
'c_return': 6,
2321
}
2422

25-
cdef inline int trace_func(Tracer self, FrameType frame, int kind, PyObject* arg) except -1:
26-
if frame.f_trace is not self:
27-
frame.f_trace = self
23+
cdef inline int trace_func(PyObject* tracer, PyFrameObject* frame, int kind, PyObject* arg) noexcept:
24+
cdef Tracer self = <Tracer?> tracer
2825

2926
handler = self.handler
3027

@@ -39,8 +36,7 @@ cdef inline int trace_func(Tracer self, FrameType frame, int kind, PyObject* arg
3936
if kind == 3 and self.depth > 0:
4037
self.depth -= 1
4138

42-
cdef Event event = Event(frame, kind, None if arg is NULL else <object> arg, self)
43-
39+
cdef Event event = Event(<FrameType> frame, kind, None, self.depth, self.calls, self.threading_support)
4440
try:
4541
fast_call(handler, event)
4642
except Exception as exc:
@@ -53,6 +49,7 @@ cdef inline int trace_func(Tracer self, FrameType frame, int kind, PyObject* arg
5349
if kind == 0:
5450
self.depth += 1
5551
self.calls += 1
52+
return 0
5653

5754

5855
cdef class Tracer:
@@ -82,9 +79,9 @@ cdef class Tracer:
8279
)
8380

8481
def __call__(self, frame, str kind, arg):
85-
trace_func(self, frame, KIND_INTS[kind], <PyObject*> arg)
82+
trace_func(<PyObject*> self, <PyFrameObject*> frame, KIND_INTS[kind], <PyObject*> arg)
8683
if kind == 0:
87-
PyEval_SetTrace(<pystate.Py_tracefunc> trace_func, <PyObject*> self)
84+
PyEval_SetTrace(trace_func, <PyObject*> self)
8885
return self
8986

9087
def trace(self, predicate):
@@ -101,7 +98,7 @@ cdef class Tracer:
10198
else:
10299
self.previous = <object>(state.c_profileobj)
103100
self._previousfunc = state.c_profilefunc
104-
PyEval_SetProfile(<pystate.Py_tracefunc> trace_func, <PyObject*> self)
101+
PyEval_SetProfile(trace_func, <PyObject*> self)
105102
else:
106103
if self.threading_support is None or self.threading_support:
107104
self._threading_previous = getattr(threading, '_trace_hook', None)
@@ -112,7 +109,7 @@ cdef class Tracer:
112109
else:
113110
self.previous = <object>(state.c_traceobj)
114111
self._previousfunc = state.c_tracefunc
115-
PyEval_SetTrace(<pystate.Py_tracefunc> trace_func, <PyObject*> self)
112+
PyEval_SetTrace(trace_func, <PyObject*> self)
116113
return self
117114

118115
def stop(self):

0 commit comments

Comments
 (0)