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

llnl / dftracer-utils / 28693295402

04 Jul 2026 03:17AM UTC coverage: 52.408% (+0.1%) from 52.278%
28693295402

push

github

hariharan-devarajan
feat: silence noisy warnings on aarch64

37318 of 92666 branches covered (40.27%)

Branch coverage included in aggregate %.

33462 of 42389 relevant lines covered (78.94%)

20557.64 hits per line

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

23.12
/src/dftracer/utils/python/json.cpp
1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3
#include <dftracer/utils/python/json.h>
4
#include <dftracer/utils/python/py_type_helpers.h>
5

6
using dftracer::utils::utilities::composites::dft::ArgsValueProxy;
7

8
PyObject *args_value_to_pyobject(const ArgsValue &v) {
360✔
9
    return std::visit(
540!
10
        [](const auto &val) -> PyObject * {
360✔
11
            using T = std::decay_t<decltype(val)>;
12
            if constexpr (std::is_same_v<T, std::monostate>) {
13
                Py_RETURN_NONE;
×
14
            } else if constexpr (std::is_same_v<T, std::string>) {
15
                return PyUnicode_FromStringAndSize(val.data(), val.size());
160✔
16
            } else if constexpr (std::is_same_v<T, std::uint64_t>) {
17
                return PyLong_FromUnsignedLongLong(val);
200✔
18
            } else if constexpr (std::is_same_v<T, std::int64_t>) {
19
                return PyLong_FromLongLong(val);
×
20
            } else if constexpr (std::is_same_v<T, double>) {
21
                return PyFloat_FromDouble(val);
×
22
            } else if constexpr (std::is_same_v<T, bool>) {
23
                return PyBool_FromLong(val ? 1 : 0);
×
24
            } else {
25
                Py_RETURN_NONE;
26
            }
27
        },
28
        v);
540✔
29
}
30

31
static const ArgsMap &get_map(JsonDictValueObject *self) {
160✔
32
    auto &ev = self->batch->events[self->event_index];
160✔
33
    return self->is_args ? ev.args : ev.top;
160!
34
}
35

36
static void JsonDictValue_dealloc(JsonDictValueObject *self) {
480✔
37
    self->batch.reset();
480✔
38
    Py_TYPE(self)->tp_free((PyObject *)self);
480✔
39
}
480✔
40

41
static Py_ssize_t JsonDictValue_length(JsonDictValueObject *self) {
×
42
    const auto &map = get_map(self);
×
43
    Py_ssize_t count = 0;
×
44
    map.for_each_member([&](std::string_view, ArgsValueProxy) { ++count; });
×
45
    if (!self->is_args && get_map(self).exists()) {
×
46
        auto &ev = self->batch->events[self->event_index];
×
47
        if (ev.args.exists()) ++count;
×
48
    }
49
    return count;
×
50
}
51

52
static PyObject *JsonDictValue_subscript(JsonDictValueObject *self,
×
53
                                         PyObject *key) {
54
    const char *key_str = PyUnicode_AsUTF8(key);
×
55
    if (!key_str) return NULL;
×
56

57
    std::string_view k(key_str);
×
58

59
    if (!self->is_args && k == "args") {
×
60
        auto &ev = self->batch->events[self->event_index];
×
61
        if (!ev.args.exists()) {
×
62
            Py_RETURN_NONE;
×
63
        }
64
        JsonDictValueObject *obj =
65
            (JsonDictValueObject *)JsonDictValueType.tp_alloc(
×
66
                &JsonDictValueType, 0);
67
        if (!obj) return NULL;
×
68
        new (&obj->batch) std::shared_ptr<JsonDictBatch>(self->batch);
×
69
        obj->event_index = self->event_index;
×
70
        obj->is_args = true;
×
71
        return (PyObject *)obj;
×
72
    }
73

74
    const auto &map = get_map(self);
×
75
    auto proxy = map[k];
×
76
    if (!proxy.exists()) {
×
77
        PyErr_SetObject(PyExc_KeyError, key);
×
78
        return NULL;
×
79
    }
80

81
    const auto &raw = map.raw();
×
82
    auto it = raw.find(k);
×
83
    if (it == raw.end()) {
×
84
        PyErr_SetObject(PyExc_KeyError, key);
×
85
        return NULL;
×
86
    }
87
    return args_value_to_pyobject(it->second);
×
88
}
89

90
static PyObject *JsonDictValue_keys(JsonDictValueObject *self,
×
91
                                    PyObject *Py_UNUSED(ignored)) {
92
    PyObject *list = PyList_New(0);
×
93
    if (!list) return NULL;
×
94

95
    const auto &map = get_map(self);
×
96
    map.for_each_member([&](std::string_view k, ArgsValueProxy) {
×
97
        PyObject *key = PyUnicode_FromStringAndSize(k.data(), k.size());
×
98
        if (key) {
×
99
            PyList_Append(list, key);
×
100
            Py_DECREF(key);
101
        }
102
    });
×
103

104
    if (!self->is_args) {
×
105
        auto &ev = self->batch->events[self->event_index];
×
106
        if (ev.args.exists()) {
×
107
            PyObject *args_key = PyUnicode_InternFromString("args");
×
108
            if (args_key) {
×
109
                PyList_Append(list, args_key);
×
110
                Py_DECREF(args_key);
111
            }
112
        }
113
    }
114

115
    return list;
×
116
}
117

118
static PyObject *JsonDictValue_values(JsonDictValueObject *self,
×
119
                                      PyObject *Py_UNUSED(ignored)) {
120
    PyObject *list = PyList_New(0);
×
121
    if (!list) return NULL;
×
122

123
    const auto &map = get_map(self);
×
124
    for (const auto &[k, v] : map.raw()) {
×
125
        PyObject *val = args_value_to_pyobject(v);
×
126
        if (val) {
×
127
            PyList_Append(list, val);
×
128
            Py_DECREF(val);
129
        }
130
    }
131

132
    if (!self->is_args) {
×
133
        auto &ev = self->batch->events[self->event_index];
×
134
        if (ev.args.exists()) {
×
135
            JsonDictValueObject *args_obj =
136
                (JsonDictValueObject *)JsonDictValueType.tp_alloc(
×
137
                    &JsonDictValueType, 0);
138
            if (args_obj) {
×
139
                new (&args_obj->batch)
×
140
                    std::shared_ptr<JsonDictBatch>(self->batch);
×
141
                args_obj->event_index = self->event_index;
×
142
                args_obj->is_args = true;
×
143
                PyList_Append(list, (PyObject *)args_obj);
×
144
                Py_DECREF(args_obj);
145
            }
146
        }
147
    }
148

149
    return list;
×
150
}
151

152
static PyObject *JsonDictValue_items(JsonDictValueObject *self,
×
153
                                     PyObject *Py_UNUSED(ignored)) {
154
    PyObject *list = PyList_New(0);
×
155
    if (!list) return NULL;
×
156

157
    const auto &map = get_map(self);
×
158
    for (const auto &[k, v] : map.raw()) {
×
159
        PyObject *key = PyUnicode_FromStringAndSize(k.data(), k.size());
×
160
        PyObject *val = args_value_to_pyobject(v);
×
161
        if (key && val) {
×
162
            PyObject *tuple = PyTuple_Pack(2, key, val);
×
163
            if (tuple) {
×
164
                PyList_Append(list, tuple);
×
165
                Py_DECREF(tuple);
166
            }
167
        }
168
        Py_XDECREF(key);
×
169
        Py_XDECREF(val);
×
170
    }
171

172
    if (!self->is_args) {
×
173
        auto &ev = self->batch->events[self->event_index];
×
174
        if (ev.args.exists()) {
×
175
            PyObject *args_key = PyUnicode_InternFromString("args");
×
176
            JsonDictValueObject *args_obj =
177
                (JsonDictValueObject *)JsonDictValueType.tp_alloc(
×
178
                    &JsonDictValueType, 0);
179
            if (args_key && args_obj) {
×
180
                new (&args_obj->batch)
×
181
                    std::shared_ptr<JsonDictBatch>(self->batch);
×
182
                args_obj->event_index = self->event_index;
×
183
                args_obj->is_args = true;
×
184
                PyObject *tuple =
185
                    PyTuple_Pack(2, args_key, (PyObject *)args_obj);
×
186
                if (tuple) {
×
187
                    PyList_Append(list, tuple);
×
188
                    Py_DECREF(tuple);
189
                }
190
            }
191
            Py_XDECREF(args_key);
×
192
            Py_XDECREF((PyObject *)args_obj);
×
193
        }
194
    }
195

196
    return list;
×
197
}
198

199
static PyObject *JsonDictValue_get(JsonDictValueObject *self, PyObject *args) {
×
200
    PyObject *key;
201
    PyObject *default_val = Py_None;
×
202
    if (!PyArg_ParseTuple(args, "O|O", &key, &default_val)) return NULL;
×
203

204
    const char *key_str = PyUnicode_AsUTF8(key);
×
205
    if (!key_str) return NULL;
×
206

207
    std::string_view k(key_str);
×
208

209
    if (!self->is_args && k == "args") {
×
210
        auto &ev = self->batch->events[self->event_index];
×
211
        if (!ev.args.exists()) {
×
212
            Py_INCREF(default_val);
×
213
            return default_val;
×
214
        }
215
        JsonDictValueObject *obj =
216
            (JsonDictValueObject *)JsonDictValueType.tp_alloc(
×
217
                &JsonDictValueType, 0);
218
        if (!obj) return NULL;
×
219
        new (&obj->batch) std::shared_ptr<JsonDictBatch>(self->batch);
×
220
        obj->event_index = self->event_index;
×
221
        obj->is_args = true;
×
222
        return (PyObject *)obj;
×
223
    }
224

225
    const auto &map = get_map(self);
×
226
    auto it = map.raw().find(k);
×
227
    if (it == map.raw().end()) {
×
228
        Py_INCREF(default_val);
×
229
        return default_val;
×
230
    }
231
    return args_value_to_pyobject(it->second);
×
232
}
233

234
static int JsonDictValue_contains(JsonDictValueObject *self, PyObject *key) {
120✔
235
    const char *key_str = PyUnicode_AsUTF8(key);
120!
236
    if (!key_str) return -1;
120✔
237

238
    std::string_view k(key_str);
120✔
239

240
    if (!self->is_args && k == "args") {
120!
241
        auto &ev = self->batch->events[self->event_index];
×
242
        return ev.args.exists() ? 1 : 0;
×
243
    }
244

245
    const auto &map = get_map(self);
120✔
246
    return map[k].exists() ? 1 : 0;
120!
247
}
60✔
248

249
static PyObject *JsonDictValue_to_dict(JsonDictValueObject *self,
40✔
250
                                       PyObject *Py_UNUSED(ignored)) {
251
    PyObject *dict = PyDict_New();
40✔
252
    if (!dict) return NULL;
40✔
253

254
    const auto &map = get_map(self);
40✔
255
    for (const auto &[k, v] : map.raw()) {
320✔
256
        PyObject *key = PyUnicode_FromStringAndSize(k.data(), k.size());
280!
257
        PyObject *val = args_value_to_pyobject(v);
280!
258
        if (!key || !val) {
280!
259
            Py_XDECREF(key);
×
260
            Py_XDECREF(val);
×
261
            Py_DECREF(dict);
262
            return NULL;
×
263
        }
264
        PyDict_SetItem(dict, key, val);
280!
265
        Py_DECREF(key);
140✔
266
        Py_DECREF(val);
140✔
267
    }
268

269
    if (!self->is_args) {
40✔
270
        auto &ev = self->batch->events[self->event_index];
40✔
271
        if (ev.args.exists()) {
40✔
272
            PyObject *args_dict = PyDict_New();
40✔
273
            if (!args_dict) {
40✔
274
                Py_DECREF(dict);
275
                return NULL;
×
276
            }
277
            for (const auto &[k, v] : ev.args.raw()) {
120✔
278
                PyObject *key = PyUnicode_FromStringAndSize(k.data(), k.size());
80!
279
                PyObject *val = args_value_to_pyobject(v);
80!
280
                if (!key || !val) {
80!
281
                    Py_XDECREF(key);
×
282
                    Py_XDECREF(val);
×
283
                    Py_DECREF(args_dict);
284
                    Py_DECREF(dict);
285
                    return NULL;
×
286
                }
287
                PyDict_SetItem(args_dict, key, val);
80!
288
                Py_DECREF(key);
40✔
289
                Py_DECREF(val);
40✔
290
            }
291
            PyDict_SetItemString(dict, "args", args_dict);
40✔
292
            Py_DECREF(args_dict);
20✔
293
        }
20✔
294
    }
20✔
295

296
    return dict;
40✔
297
}
20✔
298

299
static PyMappingMethods JsonDictValue_as_mapping = {
300
    (lenfunc)JsonDictValue_length,
301
    (binaryfunc)JsonDictValue_subscript,
302
    NULL,
303
};
304

305
static PySequenceMethods JsonDictValue_as_sequence = {
306
    NULL, NULL, NULL, NULL,
307
    NULL, NULL, NULL, (objobjproc)JsonDictValue_contains,
308
    NULL, NULL,
309
};
310

311
static PyMethodDef JsonDictValue_methods[] = {
312
    {"keys", (PyCFunction)JsonDictValue_keys, METH_NOARGS,
313
     "Return list of keys."},
314
    {"values", (PyCFunction)JsonDictValue_values, METH_NOARGS,
315
     "Return list of values."},
316
    {"items", (PyCFunction)JsonDictValue_items, METH_NOARGS,
317
     "Return list of (key, value) pairs."},
318
    {"get", (PyCFunction)JsonDictValue_get, METH_VARARGS,
319
     "Get value by key with optional default."},
320
    {"to_dict", (PyCFunction)JsonDictValue_to_dict, METH_NOARGS,
321
     "Convert to a regular Python dict."},
322
    {NULL}};
323

324
PyTypeObject JsonDictValueType = {
325
    PyVarObject_HEAD_INIT(NULL, 0) "dftracer_utils_ext.JsonDictValue",
326
    sizeof(JsonDictValueObject),       /* tp_basicsize */
327
    0,                                 /* tp_itemsize */
328
    (destructor)JsonDictValue_dealloc, /* tp_dealloc */
329
    0,                                 /* tp_vectorcall_offset */
330
    0,                                 /* tp_getattr */
331
    0,                                 /* tp_setattr */
332
    0,                                 /* tp_as_async */
333
    0,                                 /* tp_repr */
334
    0,                                 /* tp_as_number */
335
    &JsonDictValue_as_sequence,        /* tp_as_sequence */
336
    &JsonDictValue_as_mapping,         /* tp_as_mapping */
337
    0,                                 /* tp_hash */
338
    0,                                 /* tp_call */
339
    0,                                 /* tp_str */
340
    0,                                 /* tp_getattro */
341
    0,                                 /* tp_setattro */
342
    0,                                 /* tp_as_buffer */
343
    Py_TPFLAGS_DEFAULT,                /* tp_flags */
344
    "Zero-copy wrapper over a parsed DFTracer JSON event.\n"
345
    "Supports dict-like access: event['name'], event['args']['ret'].\n"
346
    "Call .to_dict() to materialize a regular Python dict.",
347
    0,                     /* tp_traverse */
348
    0,                     /* tp_clear */
349
    0,                     /* tp_richcompare */
350
    0,                     /* tp_weaklistoffset */
351
    0,                     /* tp_iter */
352
    0,                     /* tp_iternext */
353
    JsonDictValue_methods, /* tp_methods */
354
};
355

356
int init_json_dict_value(PyObject *m) {
2✔
357
    if (register_type(m, &JsonDictValueType, "JsonDictValue") < 0) return -1;
2✔
358
    return 0;
2✔
359
}
1✔
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