Skip to content

Commit 999c081

Browse files
committed
Rolled back certain C methods to Python
line_profiler/_line_profiler.pyx::_sys_monitoring_[de]register() Replaced C implementations with pure Python for maintainability
1 parent 72f79f5 commit 999c081

1 file changed

Lines changed: 20 additions & 101 deletions

File tree

line_profiler/_line_profiler.pyx

Lines changed: 20 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -99,107 +99,6 @@ cdef extern from "Python.h":
9999

100100
cdef int PyFrame_GetLineNumber(PyFrameObject *frame)
101101

102-
cdef extern from "Python.h":
103-
"""
104-
// Check for 3.12.0b1
105-
#if PY_VERSION_HEX >= 0x030c00b1
106-
// This is codified in PEP 669
107-
#define PY_MONITORING_PROFILER_ID 2
108-
#ifndef PyImport_ImportModuleAttrString
109-
// Apparently they'll add this in 3.14
110-
static PyObject* PyImport_ImportModuleAttrString(
111-
const char* mod_name, const char* attr_name)
112-
{
113-
PyObject* module = PyImport_ImportModule(mod_name);
114-
if (!module) return NULL;
115-
PyObject* attr = PyObject_GetAttrString(module, attr_name);
116-
Py_DECREF(module);
117-
return attr;
118-
}
119-
#endif
120-
static int _is_main_thread()
121-
{
122-
PyObject* swap;
123-
// Get the callables returning the thread objects
124-
PyObject* tcurr = PyImport_ImportModuleAttrString(
125-
"threading", "current_thread");
126-
if (!tcurr) return 0;
127-
PyObject* tmain = PyImport_ImportModuleAttrString(
128-
"threading", "main_thread");
129-
if (!tmain) {
130-
Py_DECREF(tcurr);
131-
return 0;
132-
}
133-
// Get the actual thread objects
134-
// - Current thread
135-
swap = PyObject_CallNoArgs(tcurr);
136-
Py_DECREF(tcurr);
137-
if (!swap) {
138-
Py_DECREF(tmain);
139-
return 0;
140-
}
141-
tcurr = swap;
142-
// - Main thread
143-
swap = PyObject_CallNoArgs(tmain);
144-
Py_DECREF(tmain);
145-
if (!swap) {
146-
Py_DECREF(tcurr);
147-
return 0;
148-
}
149-
tmain = swap;
150-
// Compare
151-
int result = PyObject_RichCompareBool(tcurr, tmain, Py_EQ);
152-
Py_DECREF(tcurr);
153-
Py_DECREF(tmain);
154-
return result;
155-
}
156-
static void _sys_monitoring_register()
157-
{ // Largely copied from `_lsprof.c`
158-
if (_is_main_thread() != 1) return;
159-
PyObject* monitoring = PyImport_ImportModuleAttrString("sys",
160-
"monitoring");
161-
if (!monitoring) return;
162-
PyObject* check = PyObject_CallMethod(monitoring,
163-
"use_tool_id",
164-
"is",
165-
PY_MONITORING_PROFILER_ID,
166-
"line_profiler");
167-
if (!check) {
168-
PyErr_Format(PyExc_ValueError,
169-
"Another profiling tool is already active");
170-
} else {
171-
Py_DECREF(check);
172-
}
173-
Py_DECREF(monitoring);
174-
return;
175-
}
176-
static void _sys_monitoring_deregister()
177-
{ // Largely copied from `_lsprof.c`
178-
if (_is_main_thread() != 1) return;
179-
PyObject* monitoring = PyImport_ImportModuleAttrString("sys",
180-
"monitoring");
181-
if (!monitoring) return;
182-
PyObject* result = PyObject_CallMethod(monitoring,
183-
"free_tool_id",
184-
"i",
185-
PY_MONITORING_PROFILER_ID);
186-
if (!result) {
187-
PyErr_Format(PyExc_RuntimeError,
188-
"Error freeing the profiling tool ID");
189-
} else {
190-
Py_DECREF(result);
191-
}
192-
Py_DECREF(monitoring);
193-
return;
194-
}
195-
#else
196-
static void _sys_monitoring_register() { return; }
197-
static void _sys_monitoring_deregister() { return; }
198-
#endif
199-
"""
200-
cdef void _sys_monitoring_register() except *
201-
cdef void _sys_monitoring_deregister() except *
202-
203102
cdef extern from "timers.c":
204103
PY_LONG_LONG hpTimer()
205104
double hpTimerUnit()
@@ -228,6 +127,26 @@ cdef inline int64 compute_line_hash(uint64 block_hash, uint64 linenum):
228127
# so it doesn't matter
229128
return block_hash ^ linenum
230129

130+
131+
if PY_VERSION_HEX < 0x030c00b1: # 3.12.0b1
132+
def _sys_monitoring_register() -> None: ...
133+
def _sys_monitoring_deregister() -> None: ...
134+
else:
135+
def _is_main_thread() -> bool:
136+
return threading.current_thread() == threading.main_thread()
137+
138+
def _sys_monitoring_register() -> None:
139+
if not _is_main_thread():
140+
return
141+
mon = sys.monitoring
142+
mon.use_tool_id(mon.PROFILER_ID, 'line_profiler')
143+
144+
def _sys_monitoring_deregister() -> None:
145+
if not _is_main_thread():
146+
return
147+
mon = sys.monitoring
148+
mon.free_tool_id(mon.PROFILER_ID)
149+
231150
def label(code):
232151
"""
233152
Return a (filename, first_lineno, func_name) tuple for a given code object.

0 commit comments

Comments
 (0)