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

llnl-asr / dftracer-utils / 36502607218

29 Sep 2026 12:20AM UTC coverage: 57.996% (+5.4%) from 52.58%
36502607218

push

github

rayandrew
Merge branch 'feat/view-as-lazyframe' into 'develop'

feat: view as lazyframe

See merge request dftracer/dftracer-utils!25

74077 of 162805 branches covered (45.5%)

Branch coverage included in aggregate %.

3652 of 3978 new or added lines in 49 files covered. (91.8%)

3464 existing lines in 85 files now uncovered.

65902 of 78556 relevant lines covered (83.89%)

179668.29 hits per line

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

1.6
/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_method.h>
5
#include <dftracer/utils/python/py_str_helpers.h>
6
#include <dftracer/utils/python/py_type_helpers.h>
7

8
using dftracer::utils::trace::ArgsValueProxy;
9

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

UNCOV
33
static const ArgsMap &get_map(JsonDictValueObject *self) {
×
UNCOV
34
    auto &ev = self->batch->events[self->event_index];
×
UNCOV
35
    return self->is_args ? ev.args : ev.top;
×
36
}
37

UNCOV
38
static void JsonDictValue_dealloc(JsonDictValueObject *self) {
×
UNCOV
39
    self->batch.reset();
×
UNCOV
40
    Py_TYPE(self)->tp_free((PyObject *)self);
×
41
}
×
42

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

54
static PyObject *JsonDictValue_subscript(JsonDictValueObject *self,
×
55
                                         PyObject *key) {
UNCOV
56
    const char *key_str = as_utf8(key);
×
57
    if (!key_str) return NULL;
×
58

59
    std::string_view k(key_str);
×
60

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

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

83
    const auto &raw = map.raw();
×
84
    auto it = raw.find(k);
×
85
    if (it == raw.end()) {
×
UNCOV
86
        PyErr_SetObject(PyExc_KeyError, key);
×
87
        return NULL;
×
88
    }
UNCOV
89
    return dftracer::utils::python::args_value_to_pyobject(it->second);
×
90
}
91

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

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

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

UNCOV
117
    return list;
×
118
}
119

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

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

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

UNCOV
151
    return list;
×
152
}
153

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

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

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

UNCOV
198
    return list;
×
199
}
200

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

UNCOV
206
    const char *key_str = as_utf8(key);
×
207
    if (!key_str) return NULL;
×
208

209
    std::string_view k(key_str);
×
210

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

227
    const auto &map = get_map(self);
×
228
    auto it = map.raw().find(k);
×
229
    if (it == map.raw().end()) {
×
UNCOV
230
        Py_INCREF(default_val);
×
231
        return default_val;
×
232
    }
UNCOV
233
    return dftracer::utils::python::args_value_to_pyobject(it->second);
×
234
}
235

UNCOV
236
static int JsonDictValue_contains(JsonDictValueObject *self, PyObject *key) {
×
UNCOV
237
    const char *key_str = as_utf8(key);
×
UNCOV
238
    if (!key_str) return -1;
×
239

UNCOV
240
    std::string_view k(key_str);
×
241

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

UNCOV
247
    const auto &map = get_map(self);
×
UNCOV
248
    return map[k].exists() ? 1 : 0;
×
249
}
250

UNCOV
251
static PyObject *JsonDictValue_to_dict(JsonDictValueObject *self,
×
252
                                       PyObject *Py_UNUSED(ignored)) {
UNCOV
253
    PyObject *dict = PyDict_New();
×
UNCOV
254
    if (!dict) return NULL;
×
255

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

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

UNCOV
299
    return dict;
×
300
}
301

302
static PyMappingMethods JsonDictValue_as_mapping = {
303
    (lenfunc)JsonDictValue_length,
304
    (binaryfunc)JsonDictValue_subscript,
305
    NULL,
306
};
307

308
static PySequenceMethods JsonDictValue_as_sequence = {
309
    NULL, NULL, NULL, NULL,
310
    NULL, NULL, NULL, (objobjproc)JsonDictValue_contains,
311
    NULL, NULL,
312
};
313

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

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

359
int dftracer::utils::python::init_json_dict_value(PyObject *m) {
2 ✔
360
    if (register_type(m, &JsonDictValueType, "JsonDictValue") < 0) return -1;
2 ✔
361
    return 0;
2 ✔
362
}
1 ✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc