Skip to content

Commit d205a63

Browse files
authored
Fix System Error on Python 3.13 and Windows (#457)
Fixes #456. The relevant crash from the test log actually seems to be the initial failure: ``` AttributeError: module 'time' has no attribute 'clock_gettime_ns' The above exception was the direct cause of the following exception: ... > _time_machine.patch_if_needed() E SystemError: <built-in function patch_if_needed> returned a result with an exception set ``` `PyObject_GetAttrString` fails to get `clock_gettime` and `clock_gettime_ns` on Windows because they only exist on Unix. It returns `NULL` and each time sets the `AttributeError` as the current error. `patch_if_needed` did not clear this, leading to Python's call check to raise a `SystemError` caused by the `AttributeError`, making time-machine fail to start travelling. I'm not sure which exact change in Python made this failure occur, so far it seems the `SystemError` should have been raised on older versions too. Ah well.
1 parent 040a757 commit d205a63

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

CHANGELOG.rst

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
Changelog
33
=========
44

5+
* Fix ``SystemError`` on Python 3.13 and Windows when starting time travelling.
6+
7+
Thanks to Bernát Gábor for the report in `Issue #456 <https://github.com/adamchainz/time-machine/issues/456>`__.
8+
59
2.14.1 (2024-03-22)
610
-------------------
711

src/_time_machine.c

+11-7
Original file line numberDiff line numberDiff line change
@@ -423,21 +423,25 @@ _time_machine_patch_if_needed(PyObject *module, PyObject *unused)
423423

424424
PyObject *time_module = PyImport_ImportModule("time");
425425

426-
427-
428-
PyCFunctionObject *time_clock_gettime = (PyCFunctionObject *) PyObject_GetAttrString(time_module, "clock_gettime");
429426
/*
430-
time.clock_gettime() is not always available
431-
e.g. on builds against old macOS = official Python.org installer
427+
time.clock_gettime(), only available on Unix platforms.
432428
*/
433-
if (time_clock_gettime != NULL) {
429+
PyCFunctionObject *time_clock_gettime = (PyCFunctionObject *) PyObject_GetAttrString(time_module, "clock_gettime");
430+
if (time_clock_gettime == NULL) {
431+
PyErr_Clear();
432+
} else {
434433
state->original_clock_gettime = time_clock_gettime->m_ml->ml_meth;
435434
time_clock_gettime->m_ml->ml_meth = _time_machine_clock_gettime;
436435
Py_DECREF(time_clock_gettime);
437436
}
438437

438+
/*
439+
time.clock_gettime_ns(), only available on Unix platforms.
440+
*/
439441
PyCFunctionObject *time_clock_gettime_ns = (PyCFunctionObject *) PyObject_GetAttrString(time_module, "clock_gettime_ns");
440-
if (time_clock_gettime_ns != NULL) {
442+
if (time_clock_gettime_ns == NULL) {
443+
PyErr_Clear();
444+
} else {
441445
state->original_clock_gettime_ns = time_clock_gettime_ns->m_ml->ml_meth;
442446
time_clock_gettime_ns->m_ml->ml_meth = _time_machine_clock_gettime_ns;
443447
Py_DECREF(time_clock_gettime_ns);

0 commit comments

Comments
 (0)