@@ -101,7 +101,7 @@ cdef extern from "Python.h":
101
101
cdef int PyFrame_GetLineNumber(PyFrameObject * frame)
102
102
103
103
cdef extern from * :
104
- """
104
+ r """
105
105
typedef struct TraceCallback {
106
106
/* Notes:
107
107
* - These fields are synonymous with the corresponding
@@ -171,6 +171,27 @@ cdef extern from *:
171
171
|| callback->c_traceobj == NULL) ;
172
172
}
173
173
174
+ #if PY_VERSION_HEX >= 0x030D00a1 // 3. 13. 0a0
175
+ #define add_module_ref PyImport_AddModuleRef
176
+ #else
177
+ inline PyObject * add_module_ref( const char * name) {
178
+ PyObject * mod = NULL, * name_str = NULL;
179
+ name_str = PyUnicode_FromString( name) ;
180
+ if ( name_str == NULL) goto cleanup;
181
+ mod = PyImport_AddModuleObject( name_str) ;
182
+ Py_XINCREF( mod) ;
183
+ cleanup:
184
+ Py_XDECREF( name_str) ;
185
+ return mod;
186
+ }
187
+ #endif
188
+ #define RAISE_IN_CALL( xc, const_msg) \
189
+ PyErr_SetString( xc,\
190
+ "in `line_profiler. _line_profiler. call_callback( ) `: " \
191
+ const_msg)
192
+ #define THIS_MODULE "line_profiler. _line_profiler"
193
+ #define DISABLE_CALLBACK "disable_line_events"
194
+
174
195
int call_callback( TraceCallback * callback, PyFrameObject * py_frame,
175
196
int what, PyObject * arg) {
176
197
/* Call the cached trace callback `callback` where appropriate,
@@ -222,33 +243,36 @@ cdef extern from *:
222
243
nullify_callback( &after) ;
223
244
restore_callback( &before) ;
224
245
225
- // Check if a frame-local callback has disabled future line
226
- // events , and revert the change in such a case (while
227
- // withholding future line events from the callback)
246
+ // Check if a callback has disabled future line events for the
247
+ // frame , and if so, revert the change while withholding future
248
+ // line events from the callback
228
249
if ( !( py_frame->f_trace_lines)
229
250
&& f_trace_lines != py_frame->f_trace_lines) {
230
251
py_frame->f_trace_lines = f_trace_lines;
231
252
if ( py_frame->f_trace != NULL && py_frame->f_trace != Py_None) {
232
- mod = PyImport_ImportModule("line_profiler._line_profiler");
253
+ // FIXME: can we get more performance by stashing a
254
+ // somewhat permanent reference to
255
+ // `line_profiler. _line_profiler. disable_line_events( ) `
256
+ // somewhere?
257
+ mod = add_module_ref( THIS_MODULE) ;
233
258
if ( mod == NULL) {
234
- PyErr_SetString(PyExc_ImportError,
235
- "cannot import "
236
- "`line_profiler._line_profiler`");
259
+ RAISE_IN_CALL( PyExc_ImportError,
260
+ "cannot import `" THIS_MODULE "`") ;
237
261
result = -1;
238
262
goto cleanup;
239
263
}
240
- dle = PyObject_GetAttrString(mod, "disable_line_events" );
264
+ dle = PyObject_GetAttrString( mod, DISABLE_CALLBACK ) ;
241
265
if ( dle == NULL) {
242
- PyErr_SetString (PyExc_AttributeError,
243
- "`line_profiler._line_profiler` has no "
244
- "attribute `disable_line_events `");
266
+ RAISE_IN_CALL ( PyExc_AttributeError,
267
+ "`line_profiler. _line_profiler` has no "
268
+ "attribute `" DISABLE_CALLBACK " `") ;
245
269
result = -1;
246
270
goto cleanup;
247
271
}
248
- // Note: don't DECREF the pointer! Nothing else is
249
- // holding a reference to it.
250
- f_trace = PyObject_CallFunctionObjArgs(dle, py_frame->f_trace,
251
- NULL);
272
+ // Note: DON'T `Py_[ X ] DECREF( ) ` the pointer! Nothing
273
+ // else is holding a reference to it.
274
+ f_trace = PyObject_CallFunctionObjArgs(
275
+ dle, py_frame->f_trace, NULL) ;
252
276
if ( f_trace == NULL) {
253
277
// No need to raise another exception, it's already
254
278
// raised in the call
0 commit comments