This commit is contained in:
Cyber MacGeddon 2026-01-27 09:26:57 +00:00
parent f7bf56e690
commit 5e7f260e55
3 changed files with 71 additions and 76 deletions

View file

@ -15,10 +15,10 @@ from trustgraph.schema import (
TextCompletionRequest, TextCompletionResponse, TextCompletionRequest, TextCompletionResponse,
DocumentRagQuery, DocumentRagResponse, DocumentRagQuery, DocumentRagResponse,
AgentRequest, AgentResponse, AgentStep, AgentRequest, AgentResponse, AgentStep,
Chunk, Triple, Triples, Value, Error, Chunk, Triple, Triples, Term, Error,
EntityContext, EntityContexts, EntityContext, EntityContexts,
GraphEmbeddings, EntityEmbeddings, GraphEmbeddings, EntityEmbeddings,
Metadata Metadata, IRI, LITERAL
) )
@ -43,7 +43,7 @@ def schema_registry():
"Chunk": Chunk, "Chunk": Chunk,
"Triple": Triple, "Triple": Triple,
"Triples": Triples, "Triples": Triples,
"Value": Value, "Term": Term,
"Error": Error, "Error": Error,
"EntityContext": EntityContext, "EntityContext": EntityContext,
"EntityContexts": EntityContexts, "EntityContexts": EntityContexts,
@ -98,26 +98,22 @@ def sample_message_data():
"collection": "test_collection", "collection": "test_collection",
"metadata": [] "metadata": []
}, },
"Value": { "Term": {
"value": "http://example.com/entity", "type": IRI,
"is_uri": True, "iri": "http://example.com/entity"
"type": ""
}, },
"Triple": { "Triple": {
"s": Value( "s": Term(
value="http://example.com/subject", type=IRI,
is_uri=True, iri="http://example.com/subject"
type=""
), ),
"p": Value( "p": Term(
value="http://example.com/predicate", type=IRI,
is_uri=True, iri="http://example.com/predicate"
type=""
), ),
"o": Value( "o": Term(
value="Object value", type=LITERAL,
is_uri=False, value="Object value"
type=""
) )
} }
} }
@ -139,10 +135,10 @@ def invalid_message_data():
{"query": "test", "user": "test", "collection": "test", "doc_limit": -1}, # Invalid doc_limit {"query": "test", "user": "test", "collection": "test", "doc_limit": -1}, # Invalid doc_limit
{"query": "test"}, # Missing required fields {"query": "test"}, # Missing required fields
], ],
"Value": [ "Term": [
{"value": None, "is_uri": True, "type": ""}, # Invalid value (None) {"type": IRI, "iri": None}, # Invalid iri (None)
{"value": "test", "is_uri": "not_boolean", "type": ""}, # Invalid is_uri {"type": "invalid_type", "value": "test"}, # Invalid type
{"value": 123, "is_uri": True, "type": ""}, # Invalid value (not string) {"type": LITERAL, "value": 123}, # Invalid value (not string)
] ]
} }

View file

@ -15,14 +15,14 @@ from trustgraph.schema import (
TextCompletionRequest, TextCompletionResponse, TextCompletionRequest, TextCompletionResponse,
DocumentRagQuery, DocumentRagResponse, DocumentRagQuery, DocumentRagResponse,
AgentRequest, AgentResponse, AgentStep, AgentRequest, AgentResponse, AgentStep,
Chunk, Triple, Triples, Value, Error, Chunk, Triple, Triples, Term, Error,
EntityContext, EntityContexts, EntityContext, EntityContexts,
GraphEmbeddings, EntityEmbeddings, GraphEmbeddings, EntityEmbeddings,
Metadata, Field, RowSchema, Metadata, Field, RowSchema,
StructuredDataSubmission, ExtractedObject, StructuredDataSubmission, ExtractedObject,
QuestionToStructuredQueryRequest, QuestionToStructuredQueryResponse, QuestionToStructuredQueryRequest, QuestionToStructuredQueryResponse,
StructuredQueryRequest, StructuredQueryResponse, StructuredQueryRequest, StructuredQueryResponse,
StructuredObjectEmbedding StructuredObjectEmbedding, IRI, LITERAL
) )
from .conftest import validate_schema_contract, serialize_deserialize_test from .conftest import validate_schema_contract, serialize_deserialize_test
@ -271,52 +271,51 @@ class TestAgentMessageContracts:
class TestGraphMessageContracts: class TestGraphMessageContracts:
"""Contract tests for Graph/Knowledge message schemas""" """Contract tests for Graph/Knowledge message schemas"""
def test_value_schema_contract(self, sample_message_data): def test_term_schema_contract(self, sample_message_data):
"""Test Value schema contract""" """Test Term schema contract"""
# Arrange # Arrange
value_data = sample_message_data["Value"] term_data = sample_message_data["Term"]
# Act & Assert # Act & Assert
assert validate_schema_contract(Value, value_data) assert validate_schema_contract(Term, term_data)
# Test URI value
uri_value = Value(**value_data)
assert uri_value.value == "http://example.com/entity"
assert uri_value.is_uri is True
# Test literal value # Test URI term
literal_value = Value( uri_term = Term(**term_data)
value="Literal text value", assert uri_term.iri == "http://example.com/entity"
is_uri=False, assert uri_term.type == IRI
type=""
# Test literal term
literal_term = Term(
type=LITERAL,
value="Literal text value"
) )
assert literal_value.value == "Literal text value" assert literal_term.value == "Literal text value"
assert literal_value.is_uri is False assert literal_term.type == LITERAL
def test_triple_schema_contract(self, sample_message_data): def test_triple_schema_contract(self, sample_message_data):
"""Test Triple schema contract""" """Test Triple schema contract"""
# Arrange # Arrange
triple_data = sample_message_data["Triple"] triple_data = sample_message_data["Triple"]
# Act & Assert - Triple uses Value objects, not dict validation # Act & Assert - Triple uses Term objects, not dict validation
triple = Triple( triple = Triple(
s=triple_data["s"], s=triple_data["s"],
p=triple_data["p"], p=triple_data["p"],
o=triple_data["o"] o=triple_data["o"]
) )
assert triple.s.value == "http://example.com/subject" assert triple.s.iri == "http://example.com/subject"
assert triple.p.value == "http://example.com/predicate" assert triple.p.iri == "http://example.com/predicate"
assert triple.o.value == "Object value" assert triple.o.value == "Object value"
assert triple.s.is_uri is True assert triple.s.type == IRI
assert triple.p.is_uri is True assert triple.p.type == IRI
assert triple.o.is_uri is False assert triple.o.type == LITERAL
def test_triples_schema_contract(self, sample_message_data): def test_triples_schema_contract(self, sample_message_data):
"""Test Triples (batch) schema contract""" """Test Triples (batch) schema contract"""
# Arrange # Arrange
metadata = Metadata(**sample_message_data["Metadata"]) metadata = Metadata(**sample_message_data["Metadata"])
triple = Triple(**sample_message_data["Triple"]) triple = Triple(**sample_message_data["Triple"])
triples_data = { triples_data = {
"metadata": metadata, "metadata": metadata,
"triples": [triple] "triples": [triple]
@ -324,11 +323,11 @@ class TestGraphMessageContracts:
# Act & Assert # Act & Assert
assert validate_schema_contract(Triples, triples_data) assert validate_schema_contract(Triples, triples_data)
triples = Triples(**triples_data) triples = Triples(**triples_data)
assert triples.metadata.id == "test-doc-123" assert triples.metadata.id == "test-doc-123"
assert len(triples.triples) == 1 assert len(triples.triples) == 1
assert triples.triples[0].s.value == "http://example.com/subject" assert triples.triples[0].s.iri == "http://example.com/subject"
def test_chunk_schema_contract(self, sample_message_data): def test_chunk_schema_contract(self, sample_message_data):
"""Test Chunk schema contract""" """Test Chunk schema contract"""
@ -349,29 +348,29 @@ class TestGraphMessageContracts:
def test_entity_context_schema_contract(self): def test_entity_context_schema_contract(self):
"""Test EntityContext schema contract""" """Test EntityContext schema contract"""
# Arrange # Arrange
entity_value = Value(value="http://example.com/entity", is_uri=True, type="") entity_term = Term(type=IRI, iri="http://example.com/entity")
entity_context_data = { entity_context_data = {
"entity": entity_value, "entity": entity_term,
"context": "Context information about the entity" "context": "Context information about the entity"
} }
# Act & Assert # Act & Assert
assert validate_schema_contract(EntityContext, entity_context_data) assert validate_schema_contract(EntityContext, entity_context_data)
entity_context = EntityContext(**entity_context_data) entity_context = EntityContext(**entity_context_data)
assert entity_context.entity.value == "http://example.com/entity" assert entity_context.entity.iri == "http://example.com/entity"
assert entity_context.context == "Context information about the entity" assert entity_context.context == "Context information about the entity"
def test_entity_contexts_batch_schema_contract(self, sample_message_data): def test_entity_contexts_batch_schema_contract(self, sample_message_data):
"""Test EntityContexts (batch) schema contract""" """Test EntityContexts (batch) schema contract"""
# Arrange # Arrange
metadata = Metadata(**sample_message_data["Metadata"]) metadata = Metadata(**sample_message_data["Metadata"])
entity_value = Value(value="http://example.com/entity", is_uri=True, type="") entity_term = Term(type=IRI, iri="http://example.com/entity")
entity_context = EntityContext( entity_context = EntityContext(
entity=entity_value, entity=entity_term,
context="Entity context" context="Entity context"
) )
entity_contexts_data = { entity_contexts_data = {
"metadata": metadata, "metadata": metadata,
"entities": [entity_context] "entities": [entity_context]
@ -379,7 +378,7 @@ class TestGraphMessageContracts:
# Act & Assert # Act & Assert
assert validate_schema_contract(EntityContexts, entity_contexts_data) assert validate_schema_contract(EntityContexts, entity_contexts_data)
entity_contexts = EntityContexts(**entity_contexts_data) entity_contexts = EntityContexts(**entity_contexts_data)
assert entity_contexts.metadata.id == "test-doc-123" assert entity_contexts.metadata.id == "test-doc-123"
assert len(entity_contexts.entities) == 1 assert len(entity_contexts.entities) == 1
@ -417,10 +416,10 @@ class TestMetadataMessageContracts:
# Act & Assert # Act & Assert
assert validate_schema_contract(Metadata, metadata_data) assert validate_schema_contract(Metadata, metadata_data)
metadata = Metadata(**metadata_data) metadata = Metadata(**metadata_data)
assert len(metadata.metadata) == 1 assert len(metadata.metadata) == 1
assert metadata.metadata[0].s.value == "http://example.com/subject" assert metadata.metadata[0].s.iri == "http://example.com/subject"
def test_error_schema_contract(self): def test_error_schema_contract(self):
"""Test Error schema contract""" """Test Error schema contract"""
@ -532,7 +531,7 @@ class TestSerializationContracts:
# Test each schema in the registry # Test each schema in the registry
for schema_name, schema_class in schema_registry.items(): for schema_name, schema_class in schema_registry.items():
if schema_name in sample_message_data: if schema_name in sample_message_data:
# Skip Triple schema as it requires special handling with Value objects # Skip Triple schema as it requires special handling with Term objects
if schema_name == "Triple": if schema_name == "Triple":
continue continue
@ -541,36 +540,36 @@ class TestSerializationContracts:
assert serialize_deserialize_test(schema_class, data), f"Serialization failed for {schema_name}" assert serialize_deserialize_test(schema_class, data), f"Serialization failed for {schema_name}"
def test_triple_serialization_contract(self, sample_message_data): def test_triple_serialization_contract(self, sample_message_data):
"""Test Triple schema serialization contract with Value objects""" """Test Triple schema serialization contract with Term objects"""
# Arrange # Arrange
triple_data = sample_message_data["Triple"] triple_data = sample_message_data["Triple"]
# Act # Act
triple = Triple( triple = Triple(
s=triple_data["s"], s=triple_data["s"],
p=triple_data["p"], p=triple_data["p"],
o=triple_data["o"] o=triple_data["o"]
) )
# Assert - Test that Value objects are properly constructed and accessible # Assert - Test that Term objects are properly constructed and accessible
assert triple.s.value == "http://example.com/subject" assert triple.s.iri == "http://example.com/subject"
assert triple.p.value == "http://example.com/predicate" assert triple.p.iri == "http://example.com/predicate"
assert triple.o.value == "Object value" assert triple.o.value == "Object value"
assert isinstance(triple.s, Value) assert isinstance(triple.s, Term)
assert isinstance(triple.p, Value) assert isinstance(triple.p, Term)
assert isinstance(triple.o, Value) assert isinstance(triple.o, Term)
def test_nested_schema_serialization_contract(self, sample_message_data): def test_nested_schema_serialization_contract(self, sample_message_data):
"""Test serialization of nested schemas""" """Test serialization of nested schemas"""
# Test Triples (contains Metadata and Triple objects) # Test Triples (contains Metadata and Triple objects)
metadata = Metadata(**sample_message_data["Metadata"]) metadata = Metadata(**sample_message_data["Metadata"])
triple = Triple(**sample_message_data["Triple"]) triple = Triple(**sample_message_data["Triple"])
triples = Triples(metadata=metadata, triples=[triple]) triples = Triples(metadata=metadata, triples=[triple])
# Verify nested objects maintain their contracts # Verify nested objects maintain their contracts
assert triples.metadata.id == "test-doc-123" assert triples.metadata.id == "test-doc-123"
assert triples.triples[0].s.value == "http://example.com/subject" assert triples.triples[0].s.iri == "http://example.com/subject"
def test_array_field_serialization_contract(self): def test_array_field_serialization_contract(self):
"""Test serialization of array fields""" """Test serialization of array fields"""

View file

@ -15,7 +15,7 @@ from trustgraph.schema import (
QuestionToStructuredQueryRequest, QuestionToStructuredQueryResponse, QuestionToStructuredQueryRequest, QuestionToStructuredQueryResponse,
StructuredQueryRequest, StructuredQueryResponse, StructuredQueryRequest, StructuredQueryResponse,
StructuredObjectEmbedding, Field, RowSchema, StructuredObjectEmbedding, Field, RowSchema,
Metadata, Error, Value Metadata, Error
) )
from .conftest import serialize_deserialize_test from .conftest import serialize_deserialize_test