Skip to content

Commit b48f8d7

Browse files
committed
ISSUE-008: Encode kwargs as structured sequence of (key, value) tuples
- Implement dict encoding in `RuntimeTracer::encode_value` by representing Python `dict` as a `Sequence` whose elements are 2-element `Tuple`s: `(String(key), encode_value(value))`. - This preserves kwargs structure losslessly without changing the `runtime_tracing` value kinds, per the proposed approach in ISSUE-008. - Keys are encoded canonically as `String` when possible; otherwise they fall back to regular value encoding. Kwarg keys are always strings. - Update the Python test to require structured kwargs encoding in `test_all_argument_kinds_recorded_on_py_start`. Rationale: Align kwargs recording with positional/varargs structure, enabling exact downstream analysis of kwargs while maintaining compatibility with the existing trace format.
1 parent 6201798 commit b48f8d7

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

codetracer-python-recorder/src/runtime_tracer.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::{Path, PathBuf};
22

33
use pyo3::prelude::*;
4-
use pyo3::types::{PyAny, PyList, PyTuple};
4+
use pyo3::types::{PyAny, PyList, PyTuple, PyDict};
55

66
use runtime_tracing::{Line, TraceEventsFileFormat, TraceWriter, TypeKind, ValueRecord, NONE_VALUE};
77
use runtime_tracing::NonStreamingTraceWriter;
@@ -127,10 +127,38 @@ impl RuntimeTracer {
127127
for item in l.iter() {
128128
elements.push(self.encode_value(_py, &item));
129129
}
130-
let ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::Seq, "Array");
130+
let ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::Seq, "List");
131131
return ValueRecord::Sequence { elements, is_slice: false, type_id: ty };
132132
}
133133

134+
// Python dict -> represent as a Sequence of (key, value) Tuples.
135+
// Keys are expected to be strings for kwargs; for non-str keys we
136+
// fall back to best-effort encoding of the key.
137+
if let Ok(d) = v.downcast::<PyDict>() {
138+
let seq_ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::Seq, "Dict");
139+
let tuple_ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::Tuple, "Tuple");
140+
let str_ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::String, "String");
141+
let mut elements: Vec<ValueRecord> = Vec::with_capacity(d.len());
142+
let items = d.items();
143+
for pair in items.iter() {
144+
if let Ok(t) = pair.downcast::<PyTuple>() {
145+
if t.len() == 2 {
146+
let key_obj = t.get_item(0).unwrap();
147+
let val_obj = t.get_item(1).unwrap();
148+
let key_rec = if let Ok(s) = key_obj.extract::<String>() {
149+
ValueRecord::String { text: s, type_id: str_ty }
150+
} else {
151+
self.encode_value(_py, &key_obj)
152+
};
153+
let val_rec = self.encode_value(_py, &val_obj);
154+
let pair_rec = ValueRecord::Tuple { elements: vec![key_rec, val_rec], type_id: tuple_ty };
155+
elements.push(pair_rec);
156+
}
157+
}
158+
}
159+
return ValueRecord::Sequence { elements, is_slice: false, type_id: seq_ty };
160+
}
161+
134162
// Fallback to Raw string representation
135163
let ty = TraceWriter::ensure_type_id(&mut self.writer, TypeKind::Raw, "Object");
136164
match v.str() {

0 commit comments

Comments
 (0)