Skip to content

Commit 72b56ac

Browse files
committed
[BugFix] Preserve uniform metadata during non-tensor concatenation
1 parent 1bb5136 commit 72b56ac

2 files changed

Lines changed: 17 additions & 6 deletions

File tree

tensordict/tensorclass.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4663,9 +4663,15 @@ def _cat_non_tensor(cls, tensors, dim=0, out=None):
46634663
f"dimension, got {batch_size} and {shape}."
46644664
)
46654665
values.extend(tensor.unbind(dim))
4666-
result = (
4667-
cls._stack_non_tensor(values, dim=dim) if values else tensors[0].clone()
4668-
)
4666+
if values and all(isinstance(tensor, cls) for tensor in tensors):
4667+
# Concatenating uniform data preserves scalar metadata, including
4668+
# callable payloads, independently of the stacking capture setting.
4669+
with set_capture_non_tensor_stack(True):
4670+
result = cls._stack_non_tensor(values, dim=dim)
4671+
else:
4672+
result = (
4673+
cls._stack_non_tensor(values, dim=dim) if values else tensors[0].clone()
4674+
)
46694675
if out is not None:
46704676
if out.batch_size != result.batch_size:
46714677
raise RuntimeError("out.batch_size and cat batch size must match.")

test/tensordict/test_nontensor.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,17 @@ def test_cat_preserves_non_tensor_values(self, capture, dim, stacked, with_out):
240240
assert result.tolist() == expected.tolist()
241241

242242
@pytest.mark.parametrize("capture", [False, True])
243-
def test_cat_non_tensor_data_out(self, capture):
243+
@pytest.mark.parametrize("with_out", [False, True])
244+
def test_cat_uniform_non_tensor_data(self, capture, with_out):
244245
items = [NonTensorData("value", batch_size=[2])] * 2
245246
out = NonTensorData("old", batch_size=[4])
246247
with set_capture_non_tensor_stack(capture):
247-
assert torch.cat(items, out=out) is out
248-
assert out.tolist() == ["value"] * 4
248+
result = torch.cat(items, out=out if with_out else None)
249+
if with_out:
250+
assert result is out
251+
assert isinstance(result, NonTensorData)
252+
assert result.data == "value"
253+
assert result.tolist() == ["value"] * 4
249254

250255
@pytest.mark.parametrize("capture", [False, True])
251256
def test_cat_pads_nested_non_tensor_values(self, capture):

0 commit comments

Comments
 (0)