Core Data Structures

DTOs for text processing with character-level span tracking

TextSpan


def TextSpan(
    text:str, start_char:int, end_char:int, label:str='sentence', metadata:Dict=<factory>
)->None:

Represents a segment of text with its original character coordinates.


TextProcessResult


def TextProcessResult(
    spans:List, metadata:Dict=<factory>
)->None:

Container for text processing results.

Testing TextSpan

TextSpan tracks character positions so you can map processed results back to the original text.

# Test TextSpan creation
span = TextSpan(
    text="Hello world.",
    start_char=0,
    end_char=12,
    label="sentence"
)

print(f"TextSpan: '{span.text}'")
print(f"Position: [{span.start_char}, {span.end_char})")
print(f"Label: {span.label}")
print(f"As dict: {span.to_dict()}")
TextSpan: 'Hello world.'
Position: [0, 12)
Label: sentence
As dict: {'text': 'Hello world.', 'start_char': 0, 'end_char': 12, 'label': 'sentence', 'metadata': {}}
# Test TextSpan with metadata
span_with_meta = TextSpan(
    text="This is a token.",
    start_char=13,
    end_char=30,
    label="token",
    metadata={"pos": "NOUN", "confidence": 0.98}
)

print(f"Span with metadata: {span_with_meta.to_dict()}")
Span with metadata: {'text': 'This is a token.', 'start_char': 13, 'end_char': 30, 'label': 'token', 'metadata': {'pos': 'NOUN', 'confidence': 0.98}}

Testing TextProcessResult

TextProcessResult holds multiple spans from a processing operation.

# Test TextProcessResult with multiple spans
original_text = "Hello world. How are you?"

result = TextProcessResult(
    spans=[
        TextSpan(text="Hello world.", start_char=0, end_char=12, label="sentence"),
        TextSpan(text="How are you?", start_char=13, end_char=25, label="sentence"),
    ],
    metadata={"processor": "example", "language": "en"}
)

print(f"Number of spans: {len(result.spans)}")
print(f"Metadata: {result.metadata}")

for i, span in enumerate(result.spans):
    print(f"  Span {i}: '{span.text}' [{span.start_char}:{span.end_char}]")
    # Verify span maps back to original text
    assert original_text[span.start_char:span.end_char] == span.text
Number of spans: 2
Metadata: {'processor': 'example', 'language': 'en'}
  Span 0: 'Hello world.' [0:12]
  Span 1: 'How are you?' [13:25]
# Test minimal result (empty spans)
empty_result = TextProcessResult(spans=[])
print(f"Empty result: {len(empty_result.spans)} spans, metadata: {empty_result.metadata}")
Empty result: 0 spans, metadata: {}