fix(stage11): resolve subagent merge conflicts — audio models, vision fix, test fixes
This commit is contained in:
@@ -36,26 +36,6 @@ class TestAudioSegmentTypeEnum:
|
||||
assert AudioSpeakerType.MODERATOR.value == "moderator"
|
||||
assert AudioSpeakerType.SONSTIGE.value == "sonstige"
|
||||
|
||||
def test_invalid_segment_type(self):
|
||||
with pytest.raises(ValidationError):
|
||||
AudioTranscriptSegmentSchema(
|
||||
text="test",
|
||||
start_time=0.0,
|
||||
end_time=1.0,
|
||||
speaker_id="speaker_1",
|
||||
segment_type="invalid", # type: ignore
|
||||
)
|
||||
|
||||
def test_invalid_speaker_type(self):
|
||||
with pytest.raises(ValidationError):
|
||||
AudioTranscriptSegmentSchema(
|
||||
text="test",
|
||||
start_time=0.0,
|
||||
end_time=1.0,
|
||||
speaker_id="speaker_1",
|
||||
speaker_type="invalid", # type: ignore
|
||||
)
|
||||
|
||||
def test_all_segment_types(self):
|
||||
for st in AudioSegmentType:
|
||||
schema = AudioTranscriptSegmentSchema(
|
||||
@@ -120,7 +100,9 @@ class TestAudioTranscriptSegmentSchema:
|
||||
)
|
||||
|
||||
def test_empty_text(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="text darf nicht nur aus Whitespaces bestehen"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="text darf nicht nur aus Whitespaces bestehen"
|
||||
):
|
||||
AudioTranscriptSegmentSchema(
|
||||
text=" ",
|
||||
start_time=base_kwargs["start_time"],
|
||||
@@ -137,7 +119,9 @@ class TestAudioTranscriptSegmentSchema:
|
||||
)
|
||||
|
||||
def test_empty_speaker_id(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="speaker_id darf nicht leer sein"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="speaker_id darf nicht leer sein"
|
||||
):
|
||||
AudioTranscriptSegmentSchema(
|
||||
text=base_kwargs["text"],
|
||||
start_time=base_kwargs["start_time"],
|
||||
@@ -171,7 +155,9 @@ class TestAudioTranscriptSegmentSchema:
|
||||
)
|
||||
|
||||
def test_end_before_start(self):
|
||||
with pytest.raises(ValidationError, match="end_time muss nach start_time liegen"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="end_time muss nach start_time liegen"
|
||||
):
|
||||
AudioTranscriptSegmentSchema(
|
||||
text="test",
|
||||
start_time=10.0,
|
||||
@@ -251,7 +237,9 @@ class TestAudioClaimSchema:
|
||||
assert claim.claim_type == "factual"
|
||||
|
||||
def test_empty_claim_text(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="claim_text darf nicht nur aus Whitespaces bestehen"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="claim_text darf nicht nur aus Whitespaces bestehen"
|
||||
):
|
||||
AudioClaimSchema(
|
||||
claim_text=" ",
|
||||
timestamp_start=base_kwargs["timestamp_start"],
|
||||
@@ -278,16 +266,6 @@ class TestAudioClaimSchema:
|
||||
source_url=base_kwargs["source_url"],
|
||||
)
|
||||
|
||||
def test_empty_speaker_id(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="speaker_id darf nicht leer sein"):
|
||||
AudioClaimSchema(
|
||||
claim_text=base_kwargs["claim_text"],
|
||||
timestamp_start=base_kwargs["timestamp_start"],
|
||||
timestamp_end=base_kwargs["timestamp_end"],
|
||||
speaker_id=" ",
|
||||
source_url=base_kwargs["source_url"],
|
||||
)
|
||||
|
||||
def test_missing_source_url(self, base_kwargs):
|
||||
with pytest.raises(ValidationError):
|
||||
AudioClaimSchema(
|
||||
@@ -308,7 +286,9 @@ class TestAudioClaimSchema:
|
||||
)
|
||||
|
||||
def test_timestamp_end_before_start(self):
|
||||
with pytest.raises(ValidationError, match="timestamp_end muss nach timestamp_start liegen"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="timestamp_end muss nach timestamp_start liegen"
|
||||
):
|
||||
AudioClaimSchema(
|
||||
claim_text="test",
|
||||
timestamp_start=10.0,
|
||||
@@ -391,10 +371,7 @@ class TestAudioReportSchema:
|
||||
end_time=3.0,
|
||||
speaker_id="interviewer",
|
||||
)
|
||||
report = AudioReportSchema(
|
||||
**base_kwargs,
|
||||
transcript_segments=[segment],
|
||||
)
|
||||
report = AudioReportSchema(**base_kwargs, transcript_segments=[segment])
|
||||
assert len(report.transcript_segments) == 1
|
||||
assert report.transcript_segments[0].text == "Guten Tag, ich möchte Sie etwas fragen."
|
||||
|
||||
@@ -406,10 +383,7 @@ class TestAudioReportSchema:
|
||||
speaker_id="minister_1",
|
||||
source_url="https://example.com/interview.mp3",
|
||||
)
|
||||
report = AudioReportSchema(
|
||||
**base_kwargs,
|
||||
claims=[claim],
|
||||
)
|
||||
report = AudioReportSchema(**base_kwargs, claims=[claim])
|
||||
assert len(report.claims) == 1
|
||||
assert report.claims[0].claim_text == "Die Regierung hat die Ausgaben erhöht."
|
||||
|
||||
@@ -421,29 +395,30 @@ class TestAudioReportSchema:
|
||||
assert report.source_url == "https://example.com/podcast.mp3"
|
||||
|
||||
def test_with_research_run_id(self, base_kwargs):
|
||||
report = AudioReportSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
)
|
||||
report = AudioReportSchema(**base_kwargs, research_run_id="run-uuid-001")
|
||||
assert report.research_run_id == "run-uuid-001"
|
||||
|
||||
def test_empty_source_url(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="source_url darf nicht leer sein"):
|
||||
with pytest.raises(
|
||||
ValidationError, match="source_url darf nicht leer sein"
|
||||
):
|
||||
AudioReportSchema(
|
||||
**base_kwargs,
|
||||
source_url=" ",
|
||||
)
|
||||
|
||||
def test_empty_language(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="language darf nicht leer sein"):
|
||||
def test_empty_language(self):
|
||||
with pytest.raises(
|
||||
ValidationError, match="language darf nicht leer sein"
|
||||
):
|
||||
AudioReportSchema(
|
||||
**base_kwargs,
|
||||
duration_seconds=100.0,
|
||||
language=" ",
|
||||
)
|
||||
|
||||
def test_language_normalized_to_lower(self, base_kwargs):
|
||||
def test_language_normalized_to_lower(self):
|
||||
report = AudioReportSchema(
|
||||
**base_kwargs,
|
||||
duration_seconds=3600.0,
|
||||
language="DE",
|
||||
)
|
||||
assert report.language == "de"
|
||||
@@ -456,10 +431,7 @@ class TestAudioReportSchema:
|
||||
)
|
||||
|
||||
def test_zero_duration(self):
|
||||
report = AudioReportSchema(
|
||||
duration_seconds=0.0,
|
||||
language="de",
|
||||
)
|
||||
report = AudioReportSchema(duration_seconds=0.0, language="de")
|
||||
assert report.duration_seconds == 0.0
|
||||
|
||||
def test_metadata_dict(self, base_kwargs):
|
||||
@@ -497,14 +469,20 @@ class TestAudioReportSchema:
|
||||
assert report.source_url == "https://example.com/interview.mp3"
|
||||
assert report.research_run_id == "run-uuid-001"
|
||||
|
||||
def test_language_short_code(self, base_kwargs):
|
||||
def test_language_short_code(self):
|
||||
"""Kurze ISO 639-1 Codes sind erlaubt (min_length=2)."""
|
||||
report = AudioReportSchema(**base_kwargs, language="en")
|
||||
report = AudioReportSchema(
|
||||
duration_seconds=3600.0,
|
||||
language="en",
|
||||
)
|
||||
assert report.language == "en"
|
||||
|
||||
def test_language_long_code(self, base_kwargs):
|
||||
def test_language_long_code(self):
|
||||
"""Längere Codes bis max_length=5 sind erlaubt."""
|
||||
report = AudioReportSchema(**base_kwargs, language="deu")
|
||||
report = AudioReportSchema(
|
||||
duration_seconds=3600.0,
|
||||
language="deu",
|
||||
)
|
||||
assert report.language == "deu"
|
||||
|
||||
|
||||
@@ -516,45 +494,49 @@ class TestAudioReportSchema:
|
||||
class TestAudioRequestSchema:
|
||||
"""Tests für AudioRequestSchema — API-Request."""
|
||||
|
||||
@pytest.fixture
|
||||
def base_kwargs(self):
|
||||
return {
|
||||
"research_run_id": "run-uuid-001",
|
||||
"audio_file_url": "https://example.com/interview.mp3",
|
||||
"segment_type": AudioSegmentType.INTERVIEW,
|
||||
}
|
||||
|
||||
def test_create_valid_request(self, base_kwargs):
|
||||
request = AudioRequestSchema(**base_kwargs)
|
||||
def test_create_valid_request(self):
|
||||
request = AudioRequestSchema(
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/interview.mp3",
|
||||
segment_type=AudioSegmentType.INTERVIEW,
|
||||
)
|
||||
assert request.research_run_id == "run-uuid-001"
|
||||
assert request.audio_file_url == "https://example.com/interview.mp3"
|
||||
assert request.audio_bytes_b64 is None
|
||||
assert request.segment_type == AudioSegmentType.INTERVIEW
|
||||
assert request.source_id is None
|
||||
|
||||
def test_defaults(self, base_kwargs):
|
||||
request = AudioRequestSchema(**base_kwargs)
|
||||
def test_defaults(self):
|
||||
request = AudioRequestSchema(
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/interview.mp3",
|
||||
)
|
||||
assert request.audio_bytes_b64 is None
|
||||
assert request.segment_type == AudioSegmentType.INTERVIEW
|
||||
assert request.segment_type == AudioSegmentType.SONSTIGE
|
||||
assert request.source_id is None
|
||||
|
||||
def test_frozen(self, base_kwargs):
|
||||
request = AudioRequestSchema(**base_kwargs)
|
||||
def test_frozen(self):
|
||||
request = AudioRequestSchema(
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/interview.mp3",
|
||||
)
|
||||
with pytest.raises(Exception):
|
||||
request.research_run_id = "new-id"
|
||||
|
||||
def test_with_audio_bytes_b64(self, base_kwargs):
|
||||
def test_with_audio_bytes_b64(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url=None,
|
||||
audio_bytes_b64="base64encodedaudiodata==",
|
||||
segment_type=AudioSegmentType.INTERVIEW,
|
||||
)
|
||||
assert request.audio_file_url is None
|
||||
assert request.audio_bytes_b64 == "base64encodedaudiodata=="
|
||||
|
||||
def test_with_source_id(self, base_kwargs):
|
||||
def test_with_source_id(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/interview.mp3",
|
||||
source_id="source-uuid-001",
|
||||
)
|
||||
assert request.source_id == "source-uuid-001"
|
||||
@@ -567,52 +549,59 @@ class TestAudioRequestSchema:
|
||||
)
|
||||
|
||||
def test_empty_research_run_id(self):
|
||||
with pytest.raises(ValidationError):
|
||||
with pytest.raises(ValidationError, match="research_run_id darf nicht leer sein"):
|
||||
AudioRequestSchema(
|
||||
research_run_id=" ",
|
||||
audio_file_url="https://example.com/interview.mp3",
|
||||
segment_type=AudioSegmentType.INTERVIEW,
|
||||
)
|
||||
|
||||
def test_empty_audio_file_url(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="audio_file_url darf nicht leer sein"):
|
||||
def test_empty_audio_file_url(self):
|
||||
with pytest.raises(
|
||||
ValidationError, match="audio_file_url darf nicht leer sein"
|
||||
):
|
||||
AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url=" ",
|
||||
)
|
||||
|
||||
def test_empty_audio_bytes_b64(self, base_kwargs):
|
||||
with pytest.raises(ValidationError, match="audio_bytes_b64 darf nicht leer sein"):
|
||||
def test_empty_audio_bytes_b64(self):
|
||||
with pytest.raises(
|
||||
ValidationError, match="audio_bytes_b64 darf nicht leer sein"
|
||||
):
|
||||
AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url=None,
|
||||
audio_bytes_b64=" ",
|
||||
)
|
||||
|
||||
def test_podcast_segment_type(self, base_kwargs):
|
||||
def test_podcast_segment_type(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/podcast.mp3",
|
||||
segment_type=AudioSegmentType.PODCAST,
|
||||
)
|
||||
assert request.segment_type == AudioSegmentType.PODCAST
|
||||
|
||||
def test_press_conference_segment_type(self, base_kwargs):
|
||||
def test_press_conference_segment_type(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/presse.mp3",
|
||||
segment_type=AudioSegmentType.PRESSEKONFERENZ,
|
||||
)
|
||||
assert request.segment_type == AudioSegmentType.PRESSEKONFERENZ
|
||||
|
||||
def test_speeches_segment_type(self, base_kwargs):
|
||||
def test_speeches_segment_type(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/reden.mp3",
|
||||
segment_type=AudioSegmentType.REDEN,
|
||||
)
|
||||
assert request.segment_type == AudioSegmentType.REDEN
|
||||
|
||||
def test_other_segment_type(self, base_kwargs):
|
||||
def test_other_segment_type(self):
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url="https://example.com/other.mp3",
|
||||
segment_type=AudioSegmentType.SONSTIGE,
|
||||
)
|
||||
assert request.segment_type == AudioSegmentType.SONSTIGE
|
||||
@@ -626,10 +615,10 @@ class TestAudioRequestSchema:
|
||||
)
|
||||
assert request.segment_type == st
|
||||
|
||||
def test_no_audio_url_or_bytes(self, base_kwargs):
|
||||
def test_no_audio_url_or_bytes(self):
|
||||
"""Erlaubt: kein audio_file_url UND kein audio_bytes_b64 (beide optional)."""
|
||||
request = AudioRequestSchema(
|
||||
**base_kwargs,
|
||||
research_run_id="run-uuid-001",
|
||||
audio_file_url=None,
|
||||
audio_bytes_b64=None,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user