• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

llnl / dftracer-utils / 26932094552

04 Jun 2026 05:08AM UTC coverage: 49.905% (-2.3%) from 52.184%
26932094552

push

github

hariharan-devarajan
chore(utils): add portable to_chars_double fallback for macOS and update zstd handling

- Introduce to_chars_double wrapper that falls back to snprintf on macOS < 13.3
- Force CPM-built zstd on Apple to avoid deployment target mismatches
- Update version patch to 8

16076 of 43875 branches covered (36.64%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 1 file covered. (0.0%)

660 existing lines in 103 files now uncovered.

21461 of 31342 relevant lines covered (68.47%)

13056.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.59
/src/dftracer/utils/python/task_handle.cpp
1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3
#include <dftracer/utils/python/task_handle.h>
4

5
#include <any>
6
#include <chrono>
7
#include <future>
8
#include <string>
9

10
static void TaskHandle_dealloc(TaskHandleObject *self) {
×
11
    self->future.~shared_future();
×
12
    self->typed_future.~shared_future();
×
13
    self->name.~basic_string();
×
14
    Py_TYPE(self)->tp_free((PyObject *)self);
×
15
}
×
16

17
static PyObject *TaskHandle_new(PyTypeObject *type, PyObject * /*args*/,
×
18
                                PyObject * /*kwds*/) {
19
    TaskHandleObject *self = (TaskHandleObject *)type->tp_alloc(type, 0);
×
20
    if (self) {
×
21
        new (&self->future) std::shared_future<void>();
×
22
        new (&self->typed_future) std::shared_future<std::any>();
×
23
        new (&self->name) std::string();
×
24
        self->has_typed_future = false;
×
25
        self->task_id = -1;
×
26
    }
27
    return (PyObject *)self;
×
28
}
29

30
static PyObject *TaskHandle_get(TaskHandleObject *self,
×
31
                                PyObject *Py_UNUSED(ignored)) {
32
    if (!self->future.valid()) {
×
33
        Py_RETURN_NONE;
×
34
    }
35
    if (self->has_typed_future) {
×
36
        std::any result;
×
37
        try {
38
            Py_BEGIN_ALLOW_THREADS result = self->typed_future.get();
×
39
            Py_END_ALLOW_THREADS
×
40
        } catch (const std::exception &e) {
×
41
            PyErr_SetString(PyExc_RuntimeError, e.what());
×
42
            return NULL;
×
43
        } catch (...) {
×
44
            PyErr_SetString(PyExc_RuntimeError, "Unknown error in task");
×
45
            return NULL;
×
46
        }
×
47
        if (result.has_value()) {
×
48
            try {
49
                PyObject *obj = std::any_cast<PyObject *>(result);
×
50
                if (obj) {
×
51
                    Py_INCREF(obj);
52
                    return obj;
×
53
                }
54
            } catch (const std::bad_any_cast &) {
×
55
                // Not a PyObject* — fall through to None
56
            }
×
57
        }
58
        Py_RETURN_NONE;
×
59
    }
×
60

61
    // Void task: .get() returns void and rethrows stored exceptions.
62
    try {
63
        Py_BEGIN_ALLOW_THREADS self->future.get();
×
64
        Py_END_ALLOW_THREADS
×
65
    } catch (const std::exception &e) {
×
66
        PyErr_SetString(PyExc_RuntimeError, e.what());
×
67
        return NULL;
×
68
    } catch (...) {
×
69
        PyErr_SetString(PyExc_RuntimeError, "Unknown error in task");
×
70
        return NULL;
×
71
    }
×
72
    Py_RETURN_NONE;
×
73
}
74

75
static PyObject *TaskHandle_wait(TaskHandleObject *self,
×
76
                                 PyObject *Py_UNUSED(ignored)) {
77
    if (!self->future.valid()) {
×
78
        Py_RETURN_NONE;
×
79
    }
80
    // Use .get() (not .wait()) so stored exceptions are rethrown.
81
    try {
82
        Py_BEGIN_ALLOW_THREADS self->future.get();
×
83
        Py_END_ALLOW_THREADS
×
84
    } catch (const std::exception &e) {
×
85
        PyErr_SetString(PyExc_RuntimeError, e.what());
×
86
        return NULL;
×
87
    } catch (...) {
×
88
        PyErr_SetString(PyExc_RuntimeError, "Unknown error in task");
×
89
        return NULL;
×
90
    }
×
91
    Py_RETURN_NONE;
×
92
}
93

94
static PyObject *TaskHandle_done(TaskHandleObject *self,
×
95
                                 PyObject *Py_UNUSED(ignored)) {
96
    if (!self->future.valid()) {
×
97
        Py_RETURN_FALSE;
×
98
    }
99
    bool is_done = self->future.wait_for(std::chrono::seconds(0)) ==
×
UNCOV
100
                   std::future_status::ready;
×
101
    return PyBool_FromLong(is_done ? 1 : 0);
×
102
}
103

104
static PyObject *TaskHandle_get_name(TaskHandleObject *self, void *) {
×
105
    return PyUnicode_FromStringAndSize(
×
106
        self->name.data(), static_cast<Py_ssize_t>(self->name.size()));
×
107
}
108

109
static PyObject *TaskHandle_get_task_id(TaskHandleObject *self, void *) {
×
110
    return PyLong_FromLongLong(static_cast<long long>(self->task_id));
×
111
}
112

113
static PyMethodDef TaskHandle_methods[] = {
114
    {"get", (PyCFunction)TaskHandle_get, METH_NOARGS,
115
     "Block until task completes and return result.\n"
116
     "Raises RuntimeError if the task failed."},
117
    {"wait", (PyCFunction)TaskHandle_wait, METH_NOARGS,
118
     "Block until task completes.\n"
119
     "Raises RuntimeError if the task failed."},
120
    {"done", (PyCFunction)TaskHandle_done, METH_NOARGS,
121
     "Return True if task has completed."},
122
    {NULL}};
123

124
static PyGetSetDef TaskHandle_getsetters[] = {
125
    {"name", (getter)TaskHandle_get_name, NULL, "Task name", NULL},
126
    {"task_id", (getter)TaskHandle_get_task_id, NULL, "Task identifier", NULL},
127
    {NULL}};
128

129
PyTypeObject TaskHandleType = {
130
    PyVarObject_HEAD_INIT(NULL, 0) "dftracer_utils_ext.TaskHandle",
131
    sizeof(TaskHandleObject),                       /* tp_basicsize */
132
    0,                                              /* tp_itemsize */
133
    (destructor)TaskHandle_dealloc,                 /* tp_dealloc */
134
    0,                                              /* tp_vectorcall_offset */
135
    0,                                              /* tp_getattr */
136
    0,                                              /* tp_setattr */
137
    0,                                              /* tp_as_async */
138
    0,                                              /* tp_repr */
139
    0,                                              /* tp_as_number */
140
    0,                                              /* tp_as_sequence */
141
    0,                                              /* tp_as_mapping */
142
    0,                                              /* tp_hash */
143
    0,                                              /* tp_call */
144
    0,                                              /* tp_str */
145
    0,                                              /* tp_getattro */
146
    0,                                              /* tp_setattro */
147
    0,                                              /* tp_as_buffer */
148
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,       /* tp_flags */
149
    "Handle to an async task submitted to Runtime", /* tp_doc */
150
    0,                                              /* tp_traverse */
151
    0,                                              /* tp_clear */
152
    0,                                              /* tp_richcompare */
153
    0,                                              /* tp_weaklistoffset */
154
    0,                                              /* tp_iter */
155
    0,                                              /* tp_iternext */
156
    TaskHandle_methods,                             /* tp_methods */
157
    0,                                              /* tp_members */
158
    TaskHandle_getsetters,                          /* tp_getset */
159
    0,                                              /* tp_base */
160
    0,                                              /* tp_dict */
161
    0,                                              /* tp_descr_get */
162
    0,                                              /* tp_descr_set */
163
    0,                                              /* tp_dictoffset */
164
    0,                                              /* tp_init */
165
    0,                                              /* tp_alloc */
166
    TaskHandle_new,                                 /* tp_new */
167
};
168

169
PyObject *create_task_handle(dftracer::utils::TaskHandle handle) {
×
170
    TaskHandleObject *obj =
171
        (TaskHandleObject *)TaskHandleType.tp_alloc(&TaskHandleType, 0);
×
172
    if (!obj) return NULL;
×
173
    new (&obj->future) std::shared_future<void>(std::move(handle.future));
×
174
    new (&obj->typed_future) std::shared_future<std::any>();
×
175
    new (&obj->name) std::string(std::move(handle.name));
×
176
    obj->has_typed_future = false;
×
177
    obj->task_id = handle.id;
×
178
    return (PyObject *)obj;
×
179
}
180

181
PyObject *create_typed_task_handle(std::shared_future<void> void_future,
×
182
                                   std::shared_future<std::any> typed_future,
183
                                   dftracer::utils::TaskIndex id,
184
                                   std::string name) {
185
    TaskHandleObject *obj =
186
        (TaskHandleObject *)TaskHandleType.tp_alloc(&TaskHandleType, 0);
×
187
    if (!obj) return NULL;
×
188
    new (&obj->future) std::shared_future<void>(std::move(void_future));
×
189
    new (&obj->typed_future)
×
190
        std::shared_future<std::any>(std::move(typed_future));
×
191
    new (&obj->name) std::string(std::move(name));
×
192
    obj->has_typed_future = true;
×
193
    obj->task_id = id;
×
194
    return (PyObject *)obj;
×
195
}
196

197
int init_task_handle(PyObject *m) {
1✔
198
    if (PyType_Ready(&TaskHandleType) < 0) return -1;
1!
199
    Py_INCREF(&TaskHandleType);
200
    if (PyModule_AddObject(m, "TaskHandle", (PyObject *)&TaskHandleType) < 0) {
1!
201
        Py_DECREF(&TaskHandleType);
202
        return -1;
×
203
    }
204
    return 0;
1✔
205
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc