Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions tests/test_tro_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,40 @@ def test_add_performance_mixed_strings_and_refs(
assert contributed["trov:arrangement"]["@id"] == "arrangement/2"
assert contributed["trov:boundTo"] == "/mnt/output"

def test_add_performance_extra_attrs(
self, temp_workspace, tmp_path, gpg_setup, trs_profile
):
"""Test that extra attributes passed to add_performance are included in the performance."""
tro = create_tro_with_gpg(
filepath=str(tmp_path / "test_tro.jsonld"),
gpg_setup=gpg_setup,
profile=trs_profile,
)
(temp_workspace / "input.txt").write_text("x")
tro.add_arrangement(str(temp_workspace), comment="A")
(temp_workspace / "output.txt").write_text("y")
tro.add_arrangement(str(temp_workspace), comment="B")

tro.add_performance(
start_time=datetime.datetime(2024, 1, 1, 10, 0, 0),
end_time=datetime.datetime(2024, 1, 1, 11, 0, 0),
comment="with attrs",
accessed_arrangement="arrangement/0",
modified_arrangement="arrangement/1",
extra_attributes={"trov:customAttr": "customValue"},
)
perf = tro.data["@graph"][0]["trov:hasPerformance"][0]
assert perf["trov:customAttr"] == "customValue"

tro.save()
tro = create_tro_with_gpg(
filepath=str(tmp_path / "test_tro.jsonld"),
gpg_setup=gpg_setup,
profile=trs_profile,
)
perf = tro.data["@graph"][0]["trov:hasPerformance"][0]
assert perf["trov:customAttr"] == "customValue"


class TestTROSigning:
"""Test TRO signing and verification."""
Expand Down
17 changes: 17 additions & 0 deletions tro_utils/models/performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class TrustedResearchPerformance(TROVModel):
accessed_arrangements: list[ArrangementBinding] = field(default_factory=list)
contributed_to_arrangements: list[ArrangementBinding] = field(default_factory=list)
attributes: list[PerformanceAttribute] = field(default_factory=list)
extra_attributes: dict[str, Any] = field(default_factory=dict)

# ------------------------------------------------------------------
# JSON-LD serialisation
Expand Down Expand Up @@ -127,6 +128,8 @@ def to_jsonld(self) -> dict[str, Any]:
result["trov:contributedToArrangement"] = [
ref.to_jsonld() for ref in self.contributed_to_arrangements
]
if self.extra_attributes:
result.update(self.extra_attributes)
return result

@classmethod
Expand Down Expand Up @@ -157,6 +160,19 @@ def _parse_refs(value: Any) -> list[ArrangementBinding]:
return [ArrangementBinding.from_jsonld(item) for item in value]
return [ArrangementBinding.from_jsonld(value)]

known_keys = {
"@id",
"@type",
"rdfs:comment",
"trov:wasConductedBy",
"trov:hasPerformanceAttribute",
"trov:startedAtTime",
"trov:endedAtTime",
"trov:accessedArrangement",
"trov:contributedToArrangement",
}
extra = {k: v for k, v in data.items() if k not in known_keys}

return cls(
performance_id=data["@id"],
comment=data.get("rdfs:comment", ""),
Expand All @@ -168,4 +184,5 @@ def _parse_refs(value: Any) -> list[ArrangementBinding]:
data.get("trov:contributedToArrangement")
),
attributes=attributes,
extra_attributes=extra,
)
4 changes: 1 addition & 3 deletions tro_utils/models/tro.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,8 @@ def _normalise_refs(value: Any) -> list[tuple[str, str | None]]:
attributes=performance_attributes,
)

# Merge extra_attributes as raw fields — stored as a side-channel dict
# via the JSON-LD round-trip (no typed model needed for forward compat)
if extra_attributes:
trp._extra_attributes = extra_attributes # type: ignore[attr-defined]
trp.extra_attributes = extra_attributes

self.performances.append(trp)
return trp
Expand Down
Loading