https://github.com/python/cpython/commit/e875c0a141cdfa5636b5fe9062a25c4dc19946e8 commit: e875c0a141cdfa5636b5fe9062a25c4dc19946e8 branch: 3.14 author: sobolevn <[email protected]> committer: sobolevn <[email protected]> date: 2026-11-03T09:05:57Z summary:
[3.14] gh-161233: Fix `TypeError` when `timer=None` was passed to `cProfile.Profile` (GH-161234) (#161239) * [3.14] gh-161233: Fix `TypeError` when `timer=None` was passed to `cProfile.Profile` (GH-161234) (cherry picked from commit e9c9a339035c9b96a5ebca8337a13140725ecf2a) Co-authored-by: sobolevn <[email protected]> files: A Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst M Lib/test/test_cprofile.py M Modules/_lsprof.c diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index 5230348c0eb68f..656143a399a7ff 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -105,6 +105,20 @@ def timer(): profiler.disable() profiler.clear() + def test_external_timer_is_none(self): + # gh-161233 + def work(): + pass + + for kwargs in ({}, {'timer': None}): + with self.subTest(kwargs=kwargs): + profiler = cProfile.Profile(**kwargs) + profiler.enable() + with support.catch_unraisable_exception() as cm: + work() + self.assertIsNone(cm.unraisable) + profiler.disable() + def test_profile_enable_disable(self): prof = self.profilerclass() # Make sure we clean ourselves up if the test fails for some reason. diff --git a/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst b/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst new file mode 100644 index 00000000000000..96e9f5e39df3ec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst @@ -0,0 +1,2 @@ +Fix unraisable :exc:`TypeError` when ``None`` was passed as a *timer* to +:class:`cProfile.Profile <profile.Profile>`. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 237919e889ca0c..a157d808d7bd19 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -92,6 +92,7 @@ _lsprof_get_state(PyObject *module) static PyTime_t CallExternalTimer(ProfilerObject *pObj) { + assert(pObj->externalTimer != NULL && pObj->externalTimer != Py_None); PyObject *o = NULL; // External timer can do arbitrary things so we need a flag to prevent @@ -1021,6 +1022,9 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { return -1; } + if (timer == Py_None) { + timer = NULL; + } self->externalTimerUnit = timeunit; Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); self->tool_id = PY_MONITORING_PROFILER_ID; _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
