Skip to content

Commit 148a1ab

Browse files
etserendclaude
andcommitted
feat(core): bump galileo-core to ^4.4.0, drop fallback ControlSpan tests (HYBIM-788)
Ports upstream commit fa93ab2 from rungalileo/galileo-python. galileo-core 4.4.0 ships native ControlSpan unconditionally, so the builtins.__import__ + importlib.reload fallback test machinery is no longer needed. Replace the two fallback tests with direct native equivalents and remove the now-unused top-level module imports from both test files. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 1e42f6a commit 148a1ab

4 files changed

Lines changed: 27 additions & 126 deletions

File tree

poetry.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ langchain = { version = ">=0.0.0,<2.0.0", optional = true }
4141
openai = { version = ">=2.8.0,<3.0.0", optional = true }
4242
openai-agents = { version = ">=0.4.0,<1.0.0", optional = true }
4343
litellm = { version = ">=1.83.14,<2.0.0", optional = true, python = ">=3.11,<3.14" }
44-
galileo-core = "^4.3.0"
44+
galileo-core = "^4.4.0"
4545
starlette = { version = ">=0.27.0", optional = true }
4646
backoff = "^2.2.1"
4747
crewai = { version = ">=0.152.0,<2.0.0", optional = true, python = ">=3.11,<3.14" }
@@ -64,7 +64,7 @@ pytest-xdist = "^3.7.0"
6464
pytest-socket = "^0.7"
6565
pytest-asyncio = "^1.0.0"
6666
requests-mock = "^1.11.0"
67-
galileo-core = { extras = ["testing"], version = "^4.3.0" }
67+
galileo-core = { extras = ["testing"], version = "^4.4.0" }
6868

6969
pytest-env = "^1.1.5"
7070
pytest-timeout = "^2.3"

tests/schemas/test_logged.py

Lines changed: 12 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
"""Tests for SDK-local ingestion models (Logged variants and content blocks)."""
22

3-
import builtins
4-
import importlib
5-
63
import pytest
74
from pydantic import ValidationError
85

9-
import splunk_ao.logger.control as control_module
10-
import splunk_ao.logger.logger as logger_module
11-
import splunk_ao.schema.logged as logged_module
126
from galileo_core.schemas.logging.llm import MessageRole
137
from galileo_core.schemas.logging.span import AgentSpan, LlmSpan, RetrieverSpan, ToolSpan, WorkflowSpan
148
from galileo_core.schemas.logging.trace import Trace
@@ -341,76 +335,20 @@ def test_full_ingest_request_roundtrip(self) -> None:
341335
assert type(tool) is ToolSpan
342336
assert tool.output == "4"
343337

344-
def test_logged_trace_roundtrip_with_fallback_control_span(self, monkeypatch: pytest.MonkeyPatch) -> None:
345-
# Given: splunk_ao.logger.control is reloaded without native ControlSpan support
346-
if not control_module.HAS_NATIVE_CONTROL_SPAN:
347-
control_payload = control_module.ControlSpan(input="selected text").model_dump(mode="python")
348-
trace = logged_module.LoggedTrace(input="query", spans=[control_payload])
349-
restored = logged_module.LoggedTrace.model_validate(trace.model_dump(mode="json"))
350-
351-
assert restored.spans[0].type == "control"
352-
assert restored.spans[0].__class__.__name__ == "LoggedControlSpan"
353-
assert restored.spans[0].model_dump(mode="json")["input"] == "selected text"
354-
return
355-
356-
original_import = builtins.__import__
357-
358-
def force_fallback_import(name, globals=None, locals=None, fromlist=(), level=0):
359-
if name == "galileo_core.schemas.logging.control":
360-
raise ImportError("forced fallback for test")
361-
return original_import(name, globals, locals, fromlist, level)
362-
363-
try:
364-
with monkeypatch.context() as context:
365-
context.setattr(builtins, "__import__", force_fallback_import)
366-
importlib.reload(control_module)
367-
importlib.reload(logged_module)
368-
369-
# When: constructing and validating a LoggedTrace containing the fallback ControlSpan payload
370-
control_payload = control_module.ControlSpan(input="selected text").model_dump(mode="python")
371-
trace = logged_module.LoggedTrace(input="query", spans=[control_payload])
372-
restored = logged_module.LoggedTrace.model_validate(trace.model_dump(mode="json"))
373-
374-
# Then: the discriminated union resolves the fallback ControlSpan cleanly
375-
assert control_module.HAS_NATIVE_CONTROL_SPAN is False
376-
assert restored.spans[0].type == "control"
377-
assert restored.spans[0].__class__.__name__ == "LoggedControlSpan"
378-
assert restored.spans[0].model_dump(mode="json")["input"] == "selected text"
379-
finally:
380-
importlib.reload(control_module)
381-
importlib.reload(logged_module)
382-
logger_module.LoggedControlSpan = logged_module.LoggedControlSpan
338+
def test_logged_trace_roundtrip_with_control_span(self) -> None:
339+
from splunk_ao.logger.control import ControlSpan
340+
control_payload = ControlSpan(input="selected text").model_dump(mode="python")
341+
trace = LoggedTrace(input="query", spans=[control_payload])
342+
restored = LoggedTrace.model_validate(trace.model_dump(mode="json"))
343+
assert restored.spans[0].type == "control"
344+
assert type(restored.spans[0]) is LoggedControlSpan
345+
assert restored.spans[0].model_dump(mode="json")["input"] == "selected text"
383346

384347
@pytest.mark.parametrize("field_name", ["id", "session_id", "trace_id", "parent_id"])
385-
def test_fallback_control_span_rejects_non_uuidish_id_fields(
386-
self, field_name: str, monkeypatch: pytest.MonkeyPatch
387-
) -> None:
388-
# Given: splunk_ao.logger.control is reloaded without native ControlSpan support
389-
if not control_module.HAS_NATIVE_CONTROL_SPAN:
390-
with pytest.raises(ValidationError):
391-
control_module.ControlSpan(input="selected text", **{field_name: 123})
392-
return
393-
394-
original_import = builtins.__import__
395-
396-
def force_fallback_import(name, globals=None, locals=None, fromlist=(), level=0):
397-
if name == "galileo_core.schemas.logging.control":
398-
raise ImportError("forced fallback for test")
399-
return original_import(name, globals, locals, fromlist, level)
400-
401-
try:
402-
with monkeypatch.context() as context:
403-
context.setattr(builtins, "__import__", force_fallback_import)
404-
importlib.reload(control_module)
405-
406-
# When/Then: non-UUID-ish id fields are rejected by the fallback schema
407-
assert control_module.HAS_NATIVE_CONTROL_SPAN is False
408-
with pytest.raises(ValidationError):
409-
control_module.ControlSpan(input="selected text", **{field_name: 123})
410-
finally:
411-
importlib.reload(control_module)
412-
importlib.reload(logged_module)
413-
logger_module.LoggedControlSpan = logged_module.LoggedControlSpan
348+
def test_control_span_rejects_non_uuidish_id_fields(self, field_name: str) -> None:
349+
from splunk_ao.logger.control import ControlSpan
350+
with pytest.raises(ValidationError):
351+
ControlSpan(input="selected text", **{field_name: 123})
414352

415353

416354
class TestLoggedAndCoreParity:

tests/test_agent_control_bridge.py

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from __future__ import annotations
22

33
import asyncio
4-
import builtins
54
import dataclasses
65
import datetime
7-
import importlib
86
import sys
97
import types
108
import uuid
@@ -13,9 +11,6 @@
1311

1412
import pytest
1513

16-
import splunk_ao.logger.control as control_module
17-
import splunk_ao.logger.logger as logger_module
18-
import splunk_ao.schema.logged as logged_module
1914
from splunk_ao.handlers.agent_control import setup_agent_control_bridge
2015
from splunk_ao.logger.control import ControlResult, ControlSpan
2116
from splunk_ao.logger.logger import SplunkAOLogger
@@ -476,52 +471,20 @@ def test_agent_control_event_streams_immediately_in_distributed_mode(
476471
@patch("splunk_ao.logger.logger.LogStreams")
477472
@patch("splunk_ao.logger.logger.Projects")
478473
@patch("splunk_ao.logger.logger.Traces")
479-
def test_add_control_span_uses_model_default_name_in_fallback_mode(
480-
mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: pytest.MonkeyPatch
474+
def test_add_control_span_uses_model_default_name(
475+
mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock
481476
) -> None:
482-
# Given: the logger is using the fallback ControlSpan model
483477
setup_mock_traces_client(mock_traces_client)
484478
setup_mock_projects_client(mock_projects_client)
485479
setup_mock_logstreams_client(mock_logstreams_client)
486-
original_import = builtins.__import__
487-
488-
def assert_fallback_default_name() -> None:
489-
logger = SplunkAOLogger(project="my_project", log_stream="my_log_stream")
490-
logger.start_trace(input="trace input")
491-
workflow = logger.add_workflow_span(input="workflow input", name="workflow")
492-
493-
# When: adding a control span without an explicit name
494-
control_span = logger.add_control_span(input="selected text", name=None)
495-
496-
# Then: the fallback model default is applied and the span is preserved
497-
assert control_span is not None
498-
assert control_module.HAS_NATIVE_CONTROL_SPAN is False
499-
assert isinstance(control_span, logged_module.LoggedControlSpan)
500-
assert isinstance(control_span, control_module.ControlSpan)
501-
assert control_span.name == "control"
502-
assert workflow.spans == [control_span]
503-
504-
if not control_module.HAS_NATIVE_CONTROL_SPAN:
505-
assert_fallback_default_name()
506-
return
507-
508-
def force_fallback_import(name, globals=None, locals=None, fromlist=(), level=0):
509-
if name == "galileo_core.schemas.logging.control":
510-
raise ImportError("forced fallback for test")
511-
return original_import(name, globals, locals, fromlist, level)
512-
513-
try:
514-
with monkeypatch.context() as context:
515-
context.setattr(builtins, "__import__", force_fallback_import)
516-
importlib.reload(control_module)
517-
importlib.reload(logged_module)
518-
context.setattr(logger_module, "LoggedControlSpan", logged_module.LoggedControlSpan)
519-
520-
assert_fallback_default_name()
521-
finally:
522-
importlib.reload(control_module)
523-
importlib.reload(logged_module)
524-
logger_module.LoggedControlSpan = logged_module.LoggedControlSpan
480+
logger = SplunkAOLogger(project="my_project", log_stream="my_log_stream")
481+
logger.start_trace(input="trace input")
482+
workflow = logger.add_workflow_span(input="workflow input", name="workflow")
483+
control_span = logger.add_control_span(input="selected text", name=None)
484+
assert control_span is not None
485+
assert isinstance(control_span, ControlSpan)
486+
assert control_span.name == ControlSpan.model_fields["name"].default
487+
assert workflow.spans == [control_span]
525488

526489

527490
@patch("splunk_ao.logger.logger.LogStreams")

0 commit comments

Comments
 (0)