diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 376db89a..88986287 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -47,6 +47,12 @@ jobs: python-version: ${{ matrix.python-version }} cache-dependency-path: "poetry.lock" + - name: Select matrix Python for Poetry + run: | + poetry env remove --all + poetry env use python + poetry run python -c "import sys; expected=tuple(map(int, '${{ matrix.python-version }}'.split('.'))); actual=sys.version_info[:2]; print('Poetry Python:', sys.version); raise SystemExit(0 if actual == expected else 'Expected Python %s, got %s' % (expected, actual))" + - name: Install invoke run: pipx install invoke diff --git a/README.md b/README.md index f9ce03b9..de98febb 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Set the following environment variables: - `GALILEO_API_KEY`: Your Galileo API key - `GALILEO_PROJECT`: (Optional) Project name - `GALILEO_LOG_STREAM`: (Optional) Log stream name -- `GALILEO_LOGGING_DISABLED`: (Optional) Disable collecting and sending logs to galileo. +- `GALILEO_LOGGING_DISABLED`: (Optional) Disable collecting and sending logs to Galileo. Note: if you would like to point to an environment other than `app.galileo.ai`, you'll need to set the `GALILEO_CONSOLE_URL` environment variable. @@ -40,8 +40,8 @@ Note: if you would like to point to an environment other than `app.galileo.ai`, ```python import os -from galileo import galileo_context -from galileo.openai import openai +from splunk_ao import galileo_context +from splunk_ao.openai import openai # If you've set your GALILEO_PROJECT and GALILEO_LOG_STREAM env vars, you can skip this step galileo_context.init(project="your-project-name", log_stream="your-log-stream-name") @@ -67,7 +67,7 @@ galileo_context.flush() You can also use the `@log` decorator to log spans. Here's how to create a workflow span with two nested LLM spans: ```python -from galileo import log +from splunk_ao import log @log def make_nested_call(): @@ -84,7 +84,7 @@ make_nested_call() Here's how to create a retriever span using the decorator: ```python -from galileo import log +from splunk_ao import log @log(span_type="retriever") def retrieve_documents(query: str): @@ -97,7 +97,7 @@ retrieve_documents(query="history") Here's how to create a tool span using the decorator: ```python -from galileo import log +from splunk_ao import log @log(span_type="tool") def tool_call(input: str = "tool call input"): @@ -113,7 +113,7 @@ galileo_context.flush() In some cases, you may want to wrap a block of code to start and flush a trace automatically. You can do this using the `galileo_context` context manager: ```python -from galileo import galileo_context +from splunk_ao import galileo_context # This will log a block of code to the project and log stream specified in the context manager with galileo_context(): @@ -124,7 +124,7 @@ with galileo_context(): `galileo_context` also allows you specify a separate project and log stream for the trace: ```python -from galileo import galileo_context +from splunk_ao import galileo_context # This will log to the project and log stream specified in the context manager with galileo_context(project="gen-ai-project", log_stream="test2"): @@ -135,7 +135,7 @@ with galileo_context(project="gen-ai-project", log_stream="test2"): You can also use the `GalileoLogger` for manual logging scenarios: ```python -from galileo.logger import GalileoLogger +from splunk_ao.logger import GalileoLogger # This will log to the project and log stream specified in the logger constructor logger = GalileoLogger(project="gen-ai-project", log_stream="test3") @@ -162,7 +162,7 @@ current Galileo log stream as the runtime target: ```python import agent_control -from galileo import galileo_context, get_agent_control_target +from splunk_ao import galileo_context, get_agent_control_target galileo_context.init(project="my-project", log_stream="prod") @@ -183,8 +183,8 @@ Control SDK or resolve log stream names over the network. If you use a direct Agent Control client instead of `agent_control.init(...)`, pass `target.target_type` and `target.target_id` on each evaluation call. -`galileo.agent_control` resolves targets for Agent Control calls. -`galileo.handlers.agent_control` bridges Agent Control telemetry into Galileo +`splunk_ao.agent_control` resolves targets for Agent Control calls. +`splunk_ao.handlers.agent_control` bridges Agent Control telemetry into Galileo logging. OpenAI streaming example: @@ -192,7 +192,7 @@ OpenAI streaming example: ```python import os -from galileo.openai import openai +from splunk_ao.openai import openai client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) @@ -210,8 +210,8 @@ In some cases (like long-running processes), it may be necessary to explicitly f ```python import os -from galileo import galileo_context -from galileo.openai import openai +from splunk_ao import galileo_context +from splunk_ao.openai import openai galileo_context.init(project="your-project-name", log_stream="your-log-stream-name") @@ -236,7 +236,7 @@ galileo_context.flush() Using the Langchain callback handler: ```python -from galileo.handlers.langchain import GalileoCallback +from splunk_ao.handlers.langchain import GalileoCallback from langchain.schema import HumanMessage from langchain_openai import ChatOpenAI @@ -259,7 +259,7 @@ print(response.content) Create a dataset: ```python -from galileo.datasets import create_dataset +from splunk_ao.datasets import create_dataset create_dataset( name="names", @@ -273,7 +273,7 @@ create_dataset( Get a dataset: ```python -from galileo.datasets import get_dataset +from splunk_ao.datasets import get_dataset dataset = get_dataset(name="names") ``` @@ -281,7 +281,7 @@ dataset = get_dataset(name="names") List all datasets: ```python -from galileo.datasets import list_datasets +from splunk_ao.datasets import list_datasets datasets = list_datasets() ``` @@ -292,7 +292,7 @@ datasets = list_datasets() > > Example: > ```python -> from galileo.schema.datasets import DatasetRecord +> from splunk_ao.schema.datasets import DatasetRecord > > record = DatasetRecord( > input="What is 2+2?", @@ -305,7 +305,7 @@ datasets = list_datasets() > > Example: > ```python -> from galileo.schema.datasets import DatasetRecord +> from splunk_ao.schema.datasets import DatasetRecord > > # Using 'output' (backward compatible) > record1 = DatasetRecord(input="What is 2+2?", output="4") @@ -322,10 +322,10 @@ datasets = list_datasets() Run an experiment with a prompt template: ```python -from galileo import Message, MessageRole -from galileo.datasets import get_dataset -from galileo.experiments import run_experiment -from galileo.prompts import create_prompt_template +from splunk_ao import Message, MessageRole +from splunk_ao.datasets import get_dataset +from splunk_ao.experiments import run_experiment +from splunk_ao.prompts import create_prompt_template prompt = create_prompt_template( name="my-prompt", @@ -349,7 +349,7 @@ Run an experiment with a runner function with local dataset: ```python import openai -from galileo.experiments import run_experiment +from splunk_ao.experiments import run_experiment dataset = [ @@ -379,7 +379,7 @@ run_experiment( Sessions allow you to group related traces together. By default, a session is created for each trace and a session name is auto-generated. If you would like to override this, you can explicitly start a session: ```python -from galileo import GalileoLogger +from splunk_ao import GalileoLogger logger = GalileoLogger(project="gen-ai-project", log_stream="my-log-stream") session_id =logger.start_session(name="my-session-name") @@ -393,7 +393,7 @@ logger.flush() You can continue a previous session by using the same session ID that was previously generated: ```python -from galileo import GalileoLogger +from splunk_ao import GalileoLogger logger = GalileoLogger(project="gen-ai-project", log_stream="my-log-stream") logger.set_session(session_id="123e4567-e89b-12d3-a456-426614174000") @@ -407,7 +407,7 @@ logger.flush() All of this can also be done using the `galileo_context` context manager: ```python -from galileo import galileo_context +from splunk_ao import galileo_context session_id = galileo_context.start_session(name="my-session-name") diff --git a/examples/langgraph/basic_langgraph.py b/examples/langgraph/basic_langgraph.py index 78c91a7c..5ac55bea 100644 --- a/examples/langgraph/basic_langgraph.py +++ b/examples/langgraph/basic_langgraph.py @@ -17,7 +17,7 @@ from langgraph.graph.message import add_messages from typing_extensions import TypedDict -from galileo.handlers.langchain import GalileoCallback +from splunk_ao.handlers.langchain import SplunkAOCallback class State(TypedDict): @@ -45,4 +45,4 @@ def node2(state: State) -> dict: graph = graph_builder.compile() graph.get_graph().print_ascii() -graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}, config={"callbacks": [GalileoCallback()]}) +graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}, config={"callbacks": [SplunkAOCallback()]}) diff --git a/examples/langgraph/with_openai.py b/examples/langgraph/with_openai.py index 700a3f11..a03de02a 100644 --- a/examples/langgraph/with_openai.py +++ b/examples/langgraph/with_openai.py @@ -15,7 +15,7 @@ from langgraph.graph.message import add_messages from typing_extensions import TypedDict -from galileo.handlers.langchain import GalileoCallback +from splunk_ao.handlers.langchain import SplunkAOCallback class State(TypedDict): @@ -42,4 +42,4 @@ def chatbot(state: State) -> dict: graph.get_graph().print_ascii() -graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}, {"callbacks": [GalileoCallback()]}) +graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}, {"callbacks": [SplunkAOCallback()]}) diff --git a/examples/templates.py b/examples/templates.py index 1a7c075e..2f4bc86e 100644 --- a/examples/templates.py +++ b/examples/templates.py @@ -3,8 +3,8 @@ # dependencies = ["galileo"] # /// -from galileo import Message, MessageRole -from galileo.prompts import create_prompt, get_prompt, get_prompts +from splunk_ao import Message, MessageRole +from splunk_ao.prompts import create_prompt, get_prompt, get_prompts # Create a global template prompt_template = create_prompt( diff --git a/galileo-a2a/README.md b/galileo-a2a/README.md index 70f257e4..6f8dc303 100644 --- a/galileo-a2a/README.md +++ b/galileo-a2a/README.md @@ -44,7 +44,7 @@ pip install galileo-a2a ## Quick Start ```python -from galileo.otel import GalileoSpanProcessor, add_galileo_span_processor +from splunk_ao.otel import GalileoSpanProcessor, add_galileo_span_processor from galileo_a2a import A2AInstrumentor from opentelemetry.sdk.trace import TracerProvider @@ -119,7 +119,7 @@ from a2a.types import ( AgentCapabilities, AgentCard, AgentSkill, Message, Role, TaskState, TaskStatus, TaskStatusUpdateEvent, TextPart, ) -from galileo.otel import GalileoSpanProcessor, add_galileo_span_processor +from splunk_ao.otel import GalileoSpanProcessor, add_galileo_span_processor from galileo_a2a import A2AInstrumentor from langchain.agents import create_agent from langchain_core.tools import tool diff --git a/galileo-a2a/examples/two_agent_demo.py b/galileo-a2a/examples/two_agent_demo.py index 7b593a6d..c0048ad8 100644 --- a/galileo-a2a/examples/two_agent_demo.py +++ b/galileo-a2a/examples/two_agent_demo.py @@ -48,10 +48,10 @@ from langgraph.graph import END, START, StateGraph from opentelemetry.instrumentation.langchain import LangchainInstrumentor from opentelemetry.sdk.trace import TracerProvider +from splunk_ao.otel import SplunkAOSpanProcessor, add_galileo_span_processor from starlette.applications import Starlette from typing_extensions import TypedDict -from galileo.otel import GalileoSpanProcessor, add_galileo_span_processor from galileo_a2a import A2AInstrumentor load_dotenv(Path(__file__).parent / ".env") @@ -61,7 +61,7 @@ # --------------------------------------------------------------------------- provider = TracerProvider() -add_galileo_span_processor(provider, GalileoSpanProcessor()) +add_galileo_span_processor(provider, SplunkAOSpanProcessor()) A2AInstrumentor().instrument(tracer_provider=provider, agent_name="orchestrator") LangchainInstrumentor().instrument(tracer_provider=provider) diff --git a/galileo-a2a/src/galileo_a2a/instrumentor.py b/galileo-a2a/src/galileo_a2a/instrumentor.py index 15ae471d..998be31f 100644 --- a/galileo-a2a/src/galileo_a2a/instrumentor.py +++ b/galileo-a2a/src/galileo_a2a/instrumentor.py @@ -32,11 +32,11 @@ class A2AInstrumentor(BaseInstrumentor): # type: ignore[misc] Example:: from opentelemetry.sdk.trace import TracerProvider - from galileo.otel import GalileoSpanProcessor, add_galileo_span_processor + from splunk_ao.otel import SplunkAOSpanProcessor, add_galileo_span_processor from galileo_a2a import A2AInstrumentor provider = TracerProvider() - add_galileo_span_processor(provider, GalileoSpanProcessor()) + add_galileo_span_processor(provider, SplunkAOSpanProcessor()) A2AInstrumentor().instrument(tracer_provider=provider, agent_name="my-agent") # To disable message content capture (e.g. for PII compliance): diff --git a/galileo-adk/CONTRIBUTING.md b/galileo-adk/CONTRIBUTING.md index 11a675ee..12e74e23 100644 --- a/galileo-adk/CONTRIBUTING.md +++ b/galileo-adk/CONTRIBUTING.md @@ -8,7 +8,7 @@ This package is part of the [galileo-python](https://github.com/rungalileo/galil ``` galileo-python/ -├── src/galileo/ ← Main Galileo SDK +├── src/splunk_ao/ ← Main Galileo SDK └── galileo-adk/ ├── src/galileo_adk/ ├── tests/ @@ -112,7 +112,7 @@ cd galileo-adk uv sync --dev ``` -This installs `galileo` in **editable mode** from `../src/galileo/`. Changes to either package are immediately available without reinstalling. +This installs `galileo` in **editable mode** from `../src/splunk_ao/`. Changes to either package are immediately available without reinstalling. ### Running Tests diff --git a/galileo-adk/README.md b/galileo-adk/README.md index ea23bf14..f63aa897 100644 --- a/galileo-adk/README.md +++ b/galileo-adk/README.md @@ -186,7 +186,7 @@ Intercept traces for custom processing before forwarding to Galileo: ```python import asyncio import os -from galileo import GalileoLogger +from splunk_ao import GalileoLogger from galileo_adk import GalileoADKPlugin from google.adk.runners import Runner from google.adk.agents import LlmAgent diff --git a/galileo-adk/src/galileo_adk/callback.py b/galileo-adk/src/galileo_adk/callback.py index eae94b69..9768a72a 100644 --- a/galileo-adk/src/galileo_adk/callback.py +++ b/galileo-adk/src/galileo_adk/callback.py @@ -7,7 +7,8 @@ from collections.abc import Callable from typing import Any -from galileo.schema.trace import TracesIngestRequest +from splunk_ao.schema.trace import TracesIngestRequest + from galileo_adk.observer import ( GalileoObserver, get_agent_name_from_tool_context, diff --git a/galileo-adk/src/galileo_adk/observer.py b/galileo-adk/src/galileo_adk/observer.py index 2d0f82b6..874cdc52 100644 --- a/galileo-adk/src/galileo_adk/observer.py +++ b/galileo-adk/src/galileo_adk/observer.py @@ -10,10 +10,11 @@ from typing import Any from uuid import UUID -from galileo import galileo_context -from galileo.handlers.base_handler import GalileoBaseHandler -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.serialization import serialize_to_str +from splunk_ao import galileo_context +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.serialization import serialize_to_str + from galileo_adk.data_converters import ( convert_adk_content_to_galileo_messages, convert_adk_tools_to_galileo_format, @@ -147,7 +148,7 @@ def __init__( if ingestion_hook: trace_builder = TraceBuilder(ingestion_hook=ingestion_hook) self._trace_builder = trace_builder - self._handler = GalileoBaseHandler( + self._handler = SplunkAOBaseHandler( galileo_logger=trace_builder, # type: ignore[arg-type] start_new_trace=True, flush_on_chain_end=True, @@ -156,7 +157,7 @@ def __init__( else: self._trace_builder = None galileo_logger = galileo_context.get_logger_instance(project=project, log_stream=log_stream) - self._handler = GalileoBaseHandler( + self._handler = SplunkAOBaseHandler( galileo_logger=galileo_logger, start_new_trace=True, flush_on_chain_end=True, @@ -170,7 +171,7 @@ def __init__( self._session_root_invocation: dict[str, str] = {} @property - def handler(self) -> GalileoBaseHandler: + def handler(self) -> SplunkAOBaseHandler: """Access the underlying handler.""" return self._handler diff --git a/galileo-adk/src/galileo_adk/plugin.py b/galileo-adk/src/galileo_adk/plugin.py index a5273339..cb35bea2 100644 --- a/galileo-adk/src/galileo_adk/plugin.py +++ b/galileo-adk/src/galileo_adk/plugin.py @@ -9,7 +9,8 @@ from typing import Any from uuid import UUID -from galileo.schema.trace import TracesIngestRequest +from splunk_ao.schema.trace import TracesIngestRequest + from galileo_adk.observer import ( GalileoObserver, get_agent_name_from_tool_context, diff --git a/galileo-adk/src/galileo_adk/span_manager.py b/galileo-adk/src/galileo_adk/span_manager.py index 9dae7780..ea824e26 100644 --- a/galileo-adk/src/galileo_adk/span_manager.py +++ b/galileo-adk/src/galileo_adk/span_manager.py @@ -7,7 +7,8 @@ from typing import Any from uuid import UUID -from galileo.handlers.base_handler import GalileoBaseHandler +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler + from galileo_adk.types import RunContext # Integration tag for all spans @@ -17,7 +18,7 @@ class SpanManager: """Manages span creation and hierarchy for Galileo observability.""" - def __init__(self, handler: GalileoBaseHandler) -> None: + def __init__(self, handler: SplunkAOBaseHandler) -> None: self._handler = handler self._run_contexts: dict[str, RunContext] = {} diff --git a/galileo-adk/src/galileo_adk/trace_builder.py b/galileo-adk/src/galileo_adk/trace_builder.py index 3a36fbae..7feb7d57 100644 --- a/galileo-adk/src/galileo_adk/trace_builder.py +++ b/galileo-adk/src/galileo_adk/trace_builder.py @@ -1,7 +1,7 @@ """Lightweight trace builder for ingestion hook mode. This module provides a TraceBuilder class that implements the same interface as -GalileoLogger for trace building, but without requiring Galileo credentials or +SplunkAOLogger for trace building, but without requiring Galileo credentials or backend connectivity. When using `ingestion_hook`, the plugin can build traces locally and pass them @@ -25,10 +25,9 @@ from galileo_core.schemas.logging.step import Metrics from galileo_core.schemas.shared.traces_logger import TracesLogger from pydantic import PrivateAttr - -from galileo.schema.logged import LoggedAgentSpan, LoggedLlmSpan, LoggedTrace, LoggedWorkflowSpan -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.retrievers import convert_to_documents +from splunk_ao.schema.logged import LoggedAgentSpan, LoggedLlmSpan, LoggedTrace, LoggedWorkflowSpan +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.retrievers import convert_to_documents _logger = logging.getLogger(__name__) @@ -47,10 +46,10 @@ def _handle_async_hook_result(task: asyncio.Task) -> None: class TraceBuilder(TracesLogger): """Lightweight trace builder for ingestion hook mode. - Inherits trace-building logic from TracesLogger (same base as GalileoLogger). + Inherits trace-building logic from TracesLogger (same base as SplunkAOLogger). No Galileo credentials or backend connection required. - This class provides the same interface as GalileoLogger for: + This class provides the same interface as SplunkAOLogger for: - Starting traces and adding spans (llm, tool, workflow, agent, retriever) - Managing parent span hierarchy - Flushing traces (calls ingestion_hook instead of API) @@ -151,8 +150,8 @@ def start_trace( ) -> LoggedTrace: """Create a new trace and add it to the list of traces. - This method mirrors GalileoLogger.start_trace() for API compatibility - with GalileoBaseHandler. + This method mirrors SplunkAOLogger.start_trace() for API compatibility + with SplunkAOBaseHandler. Parameters ---------- @@ -229,7 +228,7 @@ def add_workflow_span( """Add a workflow span to the current parent. This method wraps TracesLogger.add_workflow_span() to accept - `metadata` parameter (for GalileoBaseHandler compatibility). + `metadata` parameter (for SplunkAOBaseHandler compatibility). """ parent = self.current_parent() span = LoggedWorkflowSpan( @@ -270,7 +269,7 @@ def add_agent_span( """Add an agent span to the current parent. This method wraps TracesLogger.add_agent_span() to accept - `metadata` parameter (for GalileoBaseHandler compatibility). + `metadata` parameter (for SplunkAOBaseHandler compatibility). """ parent = self.current_parent() span = LoggedAgentSpan( @@ -319,7 +318,7 @@ def add_llm_span( """Add an LLM span to the current parent. This method wraps TracesLogger.add_llm_span() to accept - `metadata` parameter (for GalileoBaseHandler compatibility). + `metadata` parameter (for SplunkAOBaseHandler compatibility). """ span = LoggedLlmSpan( input=input, @@ -366,7 +365,7 @@ def add_tool_span( """Add a tool span to the current parent. This method wraps TracesLogger.add_tool_span() to accept - `metadata` parameter (for GalileoBaseHandler compatibility). + `metadata` parameter (for SplunkAOBaseHandler compatibility). """ return super().add_tool_span( id=uuid.uuid4(), @@ -401,7 +400,7 @@ def add_retriever_span( """Add a retriever span to the current parent. This method wraps TracesLogger.add_retriever_span() to accept - `metadata` parameter (for GalileoBaseHandler compatibility). + `metadata` parameter (for SplunkAOBaseHandler compatibility). """ documents = convert_to_documents(output, "output") redacted_documents = convert_to_documents(redacted_output, "redacted_output") diff --git a/galileo-adk/tests/conftest.py b/galileo-adk/tests/conftest.py index 4d46ef03..4e7bec75 100644 --- a/galileo-adk/tests/conftest.py +++ b/galileo-adk/tests/conftest.py @@ -8,11 +8,10 @@ from galileo_core.constants.routes import Routes as CoreRoutes from galileo_core.schemas.core.user import User from galileo_core.schemas.core.user_role import UserRole +from splunk_ao.config import SplunkAOConfig +from splunk_ao.utils.singleton import SplunkAOLoggerSingleton from test_support.config import fast_config_validation -from galileo.config import GalileoPythonConfig -from galileo.utils.singleton import GalileoLoggerSingleton - # Note: The mock_request fixture is automatically provided by galileo_core[testing] extras @@ -124,7 +123,7 @@ def mock_log_streams(mock_request: Callable) -> Generator[None, None, None]: @pytest.fixture def mock_sessions(mock_request: Callable) -> Generator[None, None, None]: - """Mock the sessions endpoints used by GalileoLogger.start_session(). + """Mock the sessions endpoints used by SplunkAOLogger.start_session(). Endpoints: - POST /projects/{project_id}/sessions/search - search sessions @@ -164,17 +163,17 @@ def set_validated_config( ) -> Generator[None, None, None]: """Automatically set up validated config for tests.""" # Reset any existing config state - if GalileoPythonConfig._instance is not None: - GalileoPythonConfig._instance.reset() + if SplunkAOConfig._instance is not None: + SplunkAOConfig._instance.reset() # Reset any cached loggers from previous tests - GalileoLoggerSingleton().reset_all() + SplunkAOLoggerSingleton().reset_all() # Bypass the slow async validation round-trips for the build only; the # endpoints are already mocked above, so this only removes event-loop cost # (notably the ~11x slower Windows IOCP poll on Python 3.11+). with fast_config_validation(): - config = GalileoPythonConfig.get(console_url="http://fake.test:8088", api_key="api-1234567890") + config = SplunkAOConfig.get(console_url="http://fake.test:8088", api_key="api-1234567890") yield # Clean up after test - GalileoLoggerSingleton().reset_all() + SplunkAOLoggerSingleton().reset_all() config.reset() diff --git a/galileo-adk/tests/test_plugin.py b/galileo-adk/tests/test_plugin.py index bb34baab..371ae5a5 100644 --- a/galileo-adk/tests/test_plugin.py +++ b/galileo-adk/tests/test_plugin.py @@ -40,7 +40,7 @@ def test_init_with_ingestion_hook_without_env_vars(self, monkeypatch: pytest.Mon traces: list = [] plugin = GalileoADKPlugin(ingestion_hook=lambda r: traces.extend(r.traces)) - # Then: plugin initializes successfully with TraceBuilder (not GalileoLogger) + # Then: plugin initializes successfully with TraceBuilder (not SplunkAOLogger) assert plugin._observer is not None assert plugin._observer._trace_builder is not None assert plugin._observer._trace_builder._ingestion_hook is not None diff --git a/galileo-adk/tests/test_trace_builder.py b/galileo-adk/tests/test_trace_builder.py index fb69d4fc..1beeac7f 100644 --- a/galileo-adk/tests/test_trace_builder.py +++ b/galileo-adk/tests/test_trace_builder.py @@ -3,8 +3,8 @@ from unittest.mock import MagicMock import pytest +from splunk_ao.schema.trace import TracesIngestRequest -from galileo.schema.trace import TracesIngestRequest from galileo_adk.trace_builder import TraceBuilder @@ -176,7 +176,7 @@ def test_add_retriever_span(self, builder_with_trace: TraceBuilder) -> None: # When: adding a retriever span span = builder.add_retriever_span( input="search query", - output=[], # TraceBuilder uses 'output' (same as GalileoLogger API) + output=[], # TraceBuilder uses 'output' (same as SplunkAOLogger API) ) # Then: span is created @@ -184,7 +184,7 @@ def test_add_retriever_span(self, builder_with_trace: TraceBuilder) -> None: def test_add_retriever_span_with_string_output(self, builder_with_trace: TraceBuilder) -> None: # Given: a trace builder with an active trace and string output - # (this is what GalileoBaseHandler passes after serialize_to_str) + # (this is what SplunkAOBaseHandler passes after serialize_to_str) builder = builder_with_trace # When: adding a retriever span with a string output diff --git a/poetry.lock b/poetry.lock index a1acafdf..77337cf4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1399,71 +1399,6 @@ files = [ [package.extras] pypi = ["pip (>=24.0)", "platformdirs (>=4.2)", "wheel (>=0.42)"] -[[package]] -name = "grpcio" -version = "1.74.0" -description = "HTTP/2-based RPC framework" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.13\" and (extra == \"crewai\" or extra == \"all\")" -files = [ - {file = "grpcio-1.74.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907"}, - {file = "grpcio-1.74.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:e154d230dc1bbbd78ad2fdc3039fa50ad7ffcf438e4eb2fa30bce223a70c7486"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8978003816c7b9eabe217f88c78bc26adc8f9304bf6a594b02e5a49b2ef9c11"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3d7bd6e3929fd2ea7fbc3f562e4987229ead70c9ae5f01501a46701e08f1ad9"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:136b53c91ac1d02c8c24201bfdeb56f8b3ac3278668cbb8e0ba49c88069e1bdc"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fe0f540750a13fd8e5da4b3eaba91a785eea8dca5ccd2bc2ffe978caa403090e"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4e4181bfc24413d1e3a37a0b7889bea68d973d4b45dd2bc68bb766c140718f82"}, - {file = "grpcio-1.74.0-cp310-cp310-win32.whl", hash = "sha256:1733969040989f7acc3d94c22f55b4a9501a30f6aaacdbccfaba0a3ffb255ab7"}, - {file = "grpcio-1.74.0-cp310-cp310-win_amd64.whl", hash = "sha256:9e912d3c993a29df6c627459af58975b2e5c897d93287939b9d5065f000249b5"}, - {file = "grpcio-1.74.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31"}, - {file = "grpcio-1.74.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f609a39f62a6f6f05c7512746798282546358a37ea93c1fcbadf8b2fed162e3"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c98e0b7434a7fa4e3e63f250456eaef52499fba5ae661c58cc5b5477d11e7182"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:662456c4513e298db6d7bd9c3b8df6f75f8752f0ba01fb653e252ed4a59b5a5d"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3d14e3c4d65e19d8430a4e28ceb71ace4728776fd6c3ce34016947474479683f"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bf949792cee20d2078323a9b02bacbbae002b9e3b9e2433f2741c15bdeba1c4"}, - {file = "grpcio-1.74.0-cp311-cp311-win32.whl", hash = "sha256:55b453812fa7c7ce2f5c88be3018fb4a490519b6ce80788d5913f3f9d7da8c7b"}, - {file = "grpcio-1.74.0-cp311-cp311-win_amd64.whl", hash = "sha256:86ad489db097141a907c559988c29718719aa3e13370d40e20506f11b4de0d11"}, - {file = "grpcio-1.74.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8"}, - {file = "grpcio-1.74.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b"}, - {file = "grpcio-1.74.0-cp312-cp312-win32.whl", hash = "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c"}, - {file = "grpcio-1.74.0-cp312-cp312-win_amd64.whl", hash = "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc"}, - {file = "grpcio-1.74.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:2bc2d7d8d184e2362b53905cb1708c84cb16354771c04b490485fa07ce3a1d89"}, - {file = "grpcio-1.74.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:c14e803037e572c177ba54a3e090d6eb12efd795d49327c5ee2b3bddb836bf01"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f6ec94f0e50eb8fa1744a731088b966427575e40c2944a980049798b127a687e"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:566b9395b90cc3d0d0c6404bc8572c7c18786ede549cdb540ae27b58afe0fb91"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1ea6176d7dfd5b941ea01c2ec34de9531ba494d541fe2057c904e601879f249"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:64229c1e9cea079420527fa8ac45d80fc1e8d3f94deaa35643c381fa8d98f362"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:0f87bddd6e27fc776aacf7ebfec367b6d49cad0455123951e4488ea99d9b9b8f"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3b03d8f2a07f0fea8c8f74deb59f8352b770e3900d143b3d1475effcb08eec20"}, - {file = "grpcio-1.74.0-cp313-cp313-win32.whl", hash = "sha256:b6a73b2ba83e663b2480a90b82fdae6a7aa6427f62bf43b29912c0cfd1aa2bfa"}, - {file = "grpcio-1.74.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd3c71aeee838299c5887230b8a1822795325ddfea635edd82954c1eaa831e24"}, - {file = "grpcio-1.74.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:4bc5fca10aaf74779081e16c2bcc3d5ec643ffd528d9e7b1c9039000ead73bae"}, - {file = "grpcio-1.74.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:6bab67d15ad617aff094c382c882e0177637da73cbc5532d52c07b4ee887a87b"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:655726919b75ab3c34cdad39da5c530ac6fa32696fb23119e36b64adcfca174a"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a2b06afe2e50ebfd46247ac3ba60cac523f54ec7792ae9ba6073c12daf26f0a"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f251c355167b2360537cf17bea2cf0197995e551ab9da6a0a59b3da5e8704f9"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f7b5882fb50632ab1e48cb3122d6df55b9afabc265582808036b6e51b9fd6b7"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:834988b6c34515545b3edd13e902c1acdd9f2465d386ea5143fb558f153a7176"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:22b834cef33429ca6cc28303c9c327ba9a3fafecbf62fae17e9a7b7163cc43ac"}, - {file = "grpcio-1.74.0-cp39-cp39-win32.whl", hash = "sha256:7d95d71ff35291bab3f1c52f52f474c632db26ea12700c2ff0ea0532cb0b5854"}, - {file = "grpcio-1.74.0-cp39-cp39-win_amd64.whl", hash = "sha256:ecde9ab49f58433abe02f9ed076c7b5be839cf0153883a6d23995937a82392fa"}, - {file = "grpcio-1.74.0.tar.gz", hash = "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.74.0)"] - [[package]] name = "grpcio" version = "1.81.1" @@ -1878,6 +1813,18 @@ vertexai = ["google-cloud-aiplatform (>=1.53.0,<2.0.0)", "jsonref (>=1.1.0,<2.0. writer = ["writer-sdk (>=2.2.0,<3.0.0)"] xai = ["xai-sdk (>=0.2.0) ; python_version >= \"3.10\""] +[[package]] +name = "invoke" +version = "2.2.1" +description = "Pythonic task execution" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "invoke-2.2.1-py3-none-any.whl", hash = "sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8"}, + {file = "invoke-2.2.1.tar.gz", hash = "sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707"}, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -6653,4 +6600,4 @@ otel = ["grpcio", "opentelemetry-api", "opentelemetry-exporter-otlp", "opentelem [metadata] lock-version = "2.1" python-versions = "^3.10,<3.15" -content-hash = "1546a6ef1f5e5adcccb5539279c40cfdd09b2e201412bc49c9dba94295631cd1" +content-hash = "24e4854295492ac9acb78014de442f7f7d452bddd8aaa4ae2791bb62332303f0" diff --git a/pydoc-markdown-handlers.yml b/pydoc-markdown-handlers.yml index e7ccf761..c666cc51 100644 --- a/pydoc-markdown-handlers.yml +++ b/pydoc-markdown-handlers.yml @@ -1,7 +1,7 @@ # Special PyDoc markdown configuration for the Galileo handlers module as this isn't created by default for some reason loaders: - type: python - search_path: [./src/galileo/handlers] + search_path: [./src/splunk_ao/handlers] ignore_when_discovered: ["__pycache__", "constants", "resources", "schema"] processors: diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml index fe6423f3..ad704bed 100644 --- a/pydoc-markdown.yml +++ b/pydoc-markdown.yml @@ -1,6 +1,6 @@ loaders: - type: python - search_path: [./src/galileo] + search_path: [./src/splunk_ao] ignore_when_discovered: ["__pycache__", "constants", "resources", "schema"] processors: diff --git a/pyproject.toml b/pyproject.toml index 634c7341..52f2f5f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,12 @@ license = "Apache-2.0" [project.urls] Repository = "https://github.com/rungalileo/galileo-python" +[tool.poetry] +packages = [ + { include = "splunk_ao", from = "src" }, + { include = "galileo", from = "src" }, +] + [project.optional-dependencies] langchain = ["langchain-core", "langchain"] openai = ["openai (>=2.8.0,<3.0.0)", "packaging (>=24.2,<25.0)", "openai-agents (>=0.4.0,<1.0.0)"] @@ -67,6 +73,7 @@ time-machine = "^2.17.0" # freezegun causes problems with pydantic model valida [tool.poetry.group.dev.dependencies] pre-commit = "^4.0.1" mypy = "^1.16.0" +invoke = "^2.2.0" openai = ">=2.8.0,<3.0.0" fastapi = "^0.115.0" ruff = "^0.12.3" @@ -262,13 +269,13 @@ ignore = [ "D", # All docstring rules (scripts are utility tools) ] # Allow local imports in these files (needed to avoid circular dependencies or conditional imports) -"src/galileo/utils/prompts.py" = ["PLC0415"] -"src/galileo/utils/datasets.py" = ["PLC0415"] -"src/galileo/utils/serialization.py" = ["PLC0415"] # Optional dependency conditional imports -"src/galileo/handlers/crewai/handler.py" = ["PLC0415"] # Version-specific conditional imports -"src/galileo/project.py" = ["PLC0415"] # Bottom-of-file circular import avoidance -"src/galileo/logger/logger.py" = ["PLC0415"] # Local imports to avoid circular dependencies -"src/galileo/logger/__init__.py" = ["PLC0415"] # Lazy import for GalileoLogger +"src/splunk_ao/utils/prompts.py" = ["PLC0415"] +"src/splunk_ao/utils/datasets.py" = ["PLC0415"] +"src/splunk_ao/utils/serialization.py" = ["PLC0415"] # Optional dependency conditional imports +"src/splunk_ao/handlers/crewai/handler.py" = ["PLC0415"] # Version-specific conditional imports +"src/splunk_ao/project.py" = ["PLC0415"] # Bottom-of-file circular import avoidance +"src/splunk_ao/logger/logger.py" = ["PLC0415"] # Local imports to avoid circular dependencies +"src/splunk_ao/logger/__init__.py" = ["PLC0415"] # Lazy import for GalileoLogger [tool.ruff.lint.isort] known-first-party = ["galileo_core"] @@ -325,7 +332,7 @@ sqlite_cache = true # Release. [tool.semantic_release] -version_variables = ["src/galileo/__init__.py:__version__"] +version_variables = ["src/splunk_ao/__init__.py:__version__"] version_toml = ["pyproject.toml:project.version"] version_source = "tag" commit_message = "chore(release): v{version}\n\nAutomatically generated by python-semantic-release" diff --git a/scripts/create_docs.py b/scripts/create_docs.py index bd397cf7..1b90f52e 100644 --- a/scripts/create_docs.py +++ b/scripts/create_docs.py @@ -780,7 +780,7 @@ def write_module(fd: FileDoc, parts: list[str]) -> None: if __name__ == "__main__": - SOURCE = "./src/galileo" + SOURCE = "./src/splunk_ao" ignore = ["__pycache__", "constants", "resources", "schema", "__future__"] details = parse_source(SOURCE, to_ignore=ignore) diff --git a/src/galileo/__future__/collaborator.py b/src/galileo/__future__/collaborator.py deleted file mode 100644 index 21f8cee0..00000000 --- a/src/galileo/__future__/collaborator.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.collaborator instead of galileo.__future__.collaborator.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.collaborator is deprecated. Use galileo.collaborator instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.collaborator import Collaborator, CollaboratorRole # noqa: E402 - -__all__ = ["Collaborator", "CollaboratorRole"] diff --git a/src/galileo/__future__/dataset.py b/src/galileo/__future__/dataset.py deleted file mode 100644 index b01804f3..00000000 --- a/src/galileo/__future__/dataset.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.dataset instead of galileo.__future__.dataset.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.dataset is deprecated. Use galileo.dataset instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.dataset import Dataset # noqa: E402 - -__all__ = ["Dataset"] diff --git a/src/galileo/__future__/experiment.py b/src/galileo/__future__/experiment.py deleted file mode 100644 index 0e6c0add..00000000 --- a/src/galileo/__future__/experiment.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.experiment instead of galileo.__future__.experiment.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.experiment is deprecated. Use galileo.experiment instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.experiment import Experiment # noqa: E402 - -__all__ = ["Experiment"] diff --git a/src/galileo/__future__/integration.py b/src/galileo/__future__/integration.py deleted file mode 100644 index d3190e1a..00000000 --- a/src/galileo/__future__/integration.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.integration instead of galileo.__future__.integration.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.integration is deprecated. Use galileo.integration instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.integration import Integration # noqa: E402 - -__all__ = ["Integration"] diff --git a/src/galileo/__future__/log_stream.py b/src/galileo/__future__/log_stream.py deleted file mode 100644 index 0aaad82c..00000000 --- a/src/galileo/__future__/log_stream.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.log_stream instead of galileo.__future__.log_stream.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.log_stream is deprecated. Use galileo.log_stream instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.log_stream import LogStream # noqa: E402 - -__all__ = ["LogStream"] diff --git a/src/galileo/__future__/metric.py b/src/galileo/__future__/metric.py deleted file mode 100644 index bf28476b..00000000 --- a/src/galileo/__future__/metric.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.metric instead of galileo.__future__.metric.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.metric is deprecated. Use galileo.metric instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.metric import BuiltInMetrics, CodeMetric, SplunkAOMetric, LlmMetric, LocalMetric, Metric # noqa: E402 - -__all__ = ["BuiltInMetrics", "CodeMetric", "SplunkAOMetric", "LlmMetric", "LocalMetric", "Metric"] diff --git a/src/galileo/__future__/model.py b/src/galileo/__future__/model.py deleted file mode 100644 index 65e95ecf..00000000 --- a/src/galileo/__future__/model.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.model instead of galileo.__future__.model.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.model is deprecated. Use galileo.model instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.model import Model # noqa: E402 - -__all__ = ["Model"] diff --git a/src/galileo/__future__/project.py b/src/galileo/__future__/project.py deleted file mode 100644 index 1c40af12..00000000 --- a/src/galileo/__future__/project.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.project instead of galileo.__future__.project.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.project is deprecated. Use galileo.project instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.project import Project # noqa: E402 - -__all__ = ["Project"] diff --git a/src/galileo/__future__/prompt.py b/src/galileo/__future__/prompt.py deleted file mode 100644 index 588c6ac0..00000000 --- a/src/galileo/__future__/prompt.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.prompt instead of galileo.__future__.prompt.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.prompt is deprecated. Use galileo.prompt instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.prompt import Prompt, PromptVersion, _parse_template_to_messages # noqa: E402 - -__all__ = ["Prompt", "PromptVersion", "_parse_template_to_messages"] diff --git a/src/galileo/__future__/shared/__init__.py b/src/galileo/__future__/shared/__init__.py deleted file mode 100644 index c82af401..00000000 --- a/src/galileo/__future__/shared/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Re-export from galileo.shared — will be deprecated once all __future__ modules are migrated.""" - -from galileo.shared.filter import boolean, date, number, text -from galileo.shared.sort import sort - -__all__ = ["boolean", "date", "number", "sort", "text"] diff --git a/src/galileo/__future__/shared/base.py b/src/galileo/__future__/shared/base.py deleted file mode 100644 index 72417ea2..00000000 --- a/src/galileo/__future__/shared/base.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.shared.base instead of galileo.__future__.shared.base.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.base is deprecated. Use galileo.shared.base instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.base import StateManagementMixin, SyncState # noqa: E402 - -__all__ = ["StateManagementMixin", "SyncState"] diff --git a/src/galileo/__future__/shared/column.py b/src/galileo/__future__/shared/column.py deleted file mode 100644 index a5bff07d..00000000 --- a/src/galileo/__future__/shared/column.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.shared.column instead of galileo.__future__.shared.column.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.column is deprecated. Use galileo.shared.column instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.column import Column, ColumnCollection, _unwrap_unset # noqa: E402 - -__all__ = ["Column", "ColumnCollection", "_unwrap_unset"] diff --git a/src/galileo/__future__/shared/experiment_result.py b/src/galileo/__future__/shared/experiment_result.py deleted file mode 100644 index 33b0fac0..00000000 --- a/src/galileo/__future__/shared/experiment_result.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Deprecated: use galileo.shared.experiment_result instead of galileo.__future__.shared.experiment_result.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.experiment_result is deprecated. " - "Use galileo.shared.experiment_result instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.experiment_result import ( # noqa: E402 - ExperimentPhaseInfo, - ExperimentRunResult, - ExperimentStatusInfo, -) - -__all__ = ["ExperimentPhaseInfo", "ExperimentRunResult", "ExperimentStatusInfo"] diff --git a/src/galileo/__future__/shared/query_result.py b/src/galileo/__future__/shared/query_result.py deleted file mode 100644 index 20ec6085..00000000 --- a/src/galileo/__future__/shared/query_result.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.shared.query_result instead of galileo.__future__.shared.query_result.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.query_result is deprecated. Use galileo.shared.query_result instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.query_result import QueryResult, _flatten_dict # noqa: E402 - -__all__ = ["QueryResult", "_flatten_dict"] diff --git a/src/galileo/__future__/shared/sort.py b/src/galileo/__future__/shared/sort.py deleted file mode 100644 index eb172ea0..00000000 --- a/src/galileo/__future__/shared/sort.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.shared.sort instead of galileo.__future__.shared.sort.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.sort is deprecated. Use galileo.shared.sort instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.sort import Sort, sort # noqa: E402 - -__all__ = ["Sort", "sort"] diff --git a/src/galileo/__future__/shared/utils.py b/src/galileo/__future__/shared/utils.py deleted file mode 100644 index 1d09384d..00000000 --- a/src/galileo/__future__/shared/utils.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.shared.utils instead of galileo.__future__.shared.utils.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.shared.utils is deprecated. Use galileo.shared.utils instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.shared.utils import classproperty # noqa: E402 - -__all__ = ["classproperty"] diff --git a/src/galileo/__future__/types.py b/src/galileo/__future__/types.py deleted file mode 100644 index d2d1b00e..00000000 --- a/src/galileo/__future__/types.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Deprecated: use galileo.types instead of galileo.__future__.types.""" - -import warnings - -warnings.warn( - "Importing from galileo.__future__.types is deprecated. Use galileo.types instead.", - DeprecationWarning, - stacklevel=2, -) - -from galileo.types import MetricSpec # noqa: E402 - -__all__ = ["MetricSpec"] diff --git a/src/galileo/__init__.py b/src/galileo/__init__.py index 193c2541..266a0340 100644 --- a/src/galileo/__init__.py +++ b/src/galileo/__init__.py @@ -1,165 +1,24 @@ -"""Galileo.""" +"""Temporary compatibility shim for the legacy ``galileo`` namespace.""" -from galileo.agent_control import AgentControlTarget, AgentControlTargetUnresolvedError, get_agent_control_target -from galileo.collaborator import Collaborator, CollaboratorRole -from galileo.configuration import Configuration -from galileo.dataset import Dataset -from galileo.decorator import SplunkAODecorator, galileo_context, log, start_session -from galileo.exceptions import ( - AuthenticationError, - BadRequestError, - ConflictError, - ForbiddenError, - SplunkAOAPIError, - SplunkAOLoggerException, - NotFoundError, - RateLimitError, - ServerError, -) -from galileo.experiment import Experiment -from galileo.handlers.agent_control import SplunkAOAgentControlBridge, setup_agent_control_bridge -from galileo.integration import Integration -from galileo.log_stream import LogStream -from galileo.logger import SplunkAOLogger -from galileo.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult, ControlSpan -from galileo.metric import CodeMetric, SplunkAOMetric, LlmMetric, LocalMetric, Metric -from galileo.model import Model -from galileo.project import Project -from galileo.prompt import Prompt -from galileo.protect import ainvoke_protect, invoke_protect -from galileo.provider import AnthropicProvider, AzureProvider, BedrockProvider, OpenAIProvider, Provider -from galileo.resources.models.document import Document -from galileo.schema.message import Message -from galileo.schema.metrics import SplunkAOMetrics, GalileoScorers -from galileo.shared.base import SyncState -from galileo.shared.exceptions import ( - APIError, - ConfigurationError, - SplunkAOFutureError, - ResourceConflictError, - ResourceNotFoundError, - ValidationError, -) -from galileo.stages import ( - create_protect_stage, - get_protect_stage, - pause_protect_stage, - resume_protect_stage, - update_protect_stage, -) -from galileo.tracing import get_tracing_headers -from galileo.types import MetricSpec -from galileo.utils.log_config import enable_console_logging -from galileo_core.helpers.api_key import create_api_key, delete_api_key, list_api_keys -from galileo_core.helpers.dependencies import is_dependency_available -from galileo_core.schemas.logging.llm import MessageRole, ToolCall, ToolCallFunction -from galileo_core.schemas.logging.session import Session -from galileo_core.schemas.logging.span import ( - AgentSpan, - LlmSpan, - RetrieverSpan, - Span, - StepWithChildSpans, - ToolSpan, - WorkflowSpan, -) -from galileo_core.schemas.logging.step import StepType -from galileo_core.schemas.logging.trace import Trace -from galileo_core.schemas.protect.execution_status import ExecutionStatus -from galileo_core.schemas.protect.payload import Payload -from galileo_core.schemas.protect.request import Request -from galileo_core.schemas.protect.response import Response -from galileo_core.schemas.protect.ruleset import Ruleset -from galileo_core.schemas.protect.stage import StageType +from __future__ import annotations -__version__ = "2.3.0" +import sys +import warnings +from importlib import import_module +from typing import Any -__all__ = [ - "APIError", - "AgentControlTarget", - "AgentControlTargetUnresolvedError", - "AgentSpan", - "AnthropicProvider", - "AuthenticationError", - "AzureProvider", - "BadRequestError", - "BedrockProvider", - "CodeMetric", - "Collaborator", - "CollaboratorRole", - "Configuration", - "ConfigurationError", - "ConflictError", - "ControlAppliesTo", - "ControlCheckStage", - "ControlResult", - "ControlSpan", - "Dataset", - "Document", - "ExecutionStatus", - "Experiment", - "ForbiddenError", - "SplunkAOAPIError", - "SplunkAOAgentControlBridge", - "SplunkAODecorator", - "SplunkAOFutureError", - "SplunkAOLogger", - "SplunkAOLoggerException", - "SplunkAOMetric", - "SplunkAOMetrics", - "GalileoScorers", - "Integration", - "LlmMetric", - "LlmSpan", - "LocalMetric", - "LogStream", - "Message", - "MessageRole", - "Metric", - "MetricSpec", - "Model", - "NotFoundError", - "OpenAIProvider", - "Payload", - "Project", - "Prompt", - "Provider", - "RateLimitError", - "Request", - "ResourceConflictError", - "ResourceNotFoundError", - "Response", - "RetrieverSpan", - "Ruleset", - "ServerError", - "Session", - "Span", - "StageType", - "StepType", - "StepWithChildSpans", - "SyncState", - "ToolCall", - "ToolCallFunction", - "ToolSpan", - "Trace", - "ValidationError", - "WorkflowSpan", - "ainvoke_protect", - "create_api_key", - "create_protect_stage", - "delete_api_key", - "enable_console_logging", - "galileo_context", - "get_agent_control_target", - "get_protect_stage", - "get_tracing_headers", - "invoke_protect", - "is_dependency_available", - "list_api_keys", - "log", - "pause_protect_stage", - "resume_protect_stage", - "setup_agent_control_bridge", - "start_session", - "update_protect_stage", -] +if not getattr(sys, "_splunk_ao_suppress_galileo_deprecation_warning", False): + warnings.warn( + "The 'galileo' namespace is deprecated and will be removed in a future HYBIM task; use 'splunk_ao' instead.", + DeprecationWarning, + stacklevel=2, + ) + + +def __getattr__(name: str) -> Any: + return getattr(import_module("splunk_ao"), name) + + +def __dir__() -> list[str]: + target = import_module("splunk_ao") + return sorted(set(globals()) | set(getattr(target, "__all__", []))) diff --git a/src/galileo/exceptions.py b/src/galileo/exceptions.py index 58113df4..022932a1 100644 --- a/src/galileo/exceptions.py +++ b/src/galileo/exceptions.py @@ -1,174 +1,3 @@ -"""Galileo SDK exceptions.""" +"""Generated-resource compatibility exports for legacy ``galileo.exceptions`` imports.""" -from typing import Any, overload - -__all__ = [ - "AuthenticationError", - "BadRequestError", - "ConflictError", - "ForbiddenError", - "SplunkAOAPIError", - "SplunkAOLoggerException", - "NotFoundError", - "RateLimitError", - "ServerError", -] - -# Sentinel for "argument not provided" so the message overload of NotFoundError can -# reject _any_ explicit second argument (including ``b""``), not just non-empty bytes. -_UNSET: Any = object() - - -class SplunkAOLoggerException(Exception): - """Exception raised by SplunkAOLogger.""" - - -class SplunkAOAPIError(Exception): - """Base class for Galileo API HTTP errors with actionable messages.""" - - def __init__(self, status_code: int, content: bytes, message: str): - self.status_code = status_code - self.content = content - self.message = message - response_text = content.decode(errors="ignore") - super().__init__(f"{message} (HTTP {status_code})\n\nResponse: {response_text}") - - -class BadRequestError(SplunkAOAPIError): - """HTTP 400 - The request was malformed or invalid.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__(status_code, content, "Bad request. Check your request parameters and body format.") - - -class AuthenticationError(SplunkAOAPIError): - """HTTP 401 - Authentication failed.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__( - status_code, - content, - "Authentication failed. Check your API key is valid and not expired. " - "Set via SPLUNK_AO_API_KEY environment variable or pass api_key= when initializing the client.", - ) - - -class ForbiddenError(SplunkAOAPIError): - """HTTP 403 - Insufficient permissions.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__( - status_code, - content, - "Permission denied. Your API key doesn't have access to this resource. " - "Check your organization and project permissions.", - ) - - -class NotFoundError(SplunkAOAPIError): - r"""HTTP 404 - Resource not found. - - Parameters - ---------- - status_code_or_message : int | str - Either an HTTP status code (``int``, paired with ``content``) or a - full message string (``str``, used on its own). - content : bytes, optional - Raw response body. Only valid alongside an ``int`` status code; on the - message path it must be omitted. - - Notes - ----- - Two construction paths are supported, exposed via ``@overload`` so type - checkers see the right shape per call site: - - - ``NotFoundError(status_code, content)`` — built from an HTTP 404 response - by the generated client. Uses the standard "Resource not found…" message. - - ``NotFoundError(message)`` — built from an SDK-level lookup that has no - HTTP response (e.g. resolving a project from env vars). The string is the - full message; no ``content`` argument is accepted. - - The runtime constructor also enforces the contract. The following all raise - ``TypeError`` instead of producing nonsensical state: - - - Mixing shapes: ``NotFoundError("msg", b"")`` / ``NotFoundError("msg", b"body")`` - - Passing ``None``: ``NotFoundError(None)`` - - Passing ``bool``: ``NotFoundError(True, b"x")`` (``bool`` is technically an - ``int`` subclass but is rejected explicitly to avoid silent acceptance) - - Examples - -------- - >>> NotFoundError(404, b"{\\"detail\\": ...}") # HTTP response path - >>> NotFoundError("Project \\"foo\\" not found.") # SDK lookup path - """ - - @overload - def __init__(self, message: str) -> None: ... - @overload - def __init__(self, status_code: int, content: bytes) -> None: ... - - def __init__(self, status_code_or_message: int | str, content: bytes = _UNSET) -> None: - if isinstance(status_code_or_message, str): - if content is not _UNSET: - raise TypeError( - "NotFoundError(message) does not accept a content argument. " - "Use NotFoundError(status_code, content) for HTTP-style construction." - ) - self.status_code = 404 - self.content = b"" - self.message = status_code_or_message - Exception.__init__(self, status_code_or_message) - # mypy narrows to ``int`` here from the ``int | str`` annotation, so the - # ``not isinstance(..., bool)`` half looks redundant statically — but at - # runtime ``bool`` is an ``int`` subclass, so this guard is real - # protection against callers passing ``True``/``False`` accidentally. - elif isinstance(status_code_or_message, int) and not isinstance( # type: ignore[redundant-expr] - status_code_or_message, bool - ): - super().__init__( - status_code_or_message, - b"" if content is _UNSET else content, - "Resource not found. The requested project, dataset, or resource doesn't exist. " - "Verify the ID or name is correct.", - ) - else: - raise TypeError( - "NotFoundError requires either (status_code: int, content: bytes) " - f"or (message: str); got {type(status_code_or_message).__name__}." - ) - - -class ConflictError(SplunkAOAPIError): - """HTTP 409 - Resource conflict.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__( - status_code, - content, - "Resource conflict. A resource with this name or ID already exists, " - "or the operation conflicts with the current state.", - ) - - -class RateLimitError(SplunkAOAPIError): - """HTTP 429 - Rate limit exceeded.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__( - status_code, - content, - "Rate limit exceeded. Too many requests. Please wait before retrying. " - "Consider adding delays between API calls.", - ) - - -class ServerError(SplunkAOAPIError): - """HTTP 5xx - Server-side error.""" - - def __init__(self, status_code: int, content: bytes): - super().__init__( - status_code, - content, - "Server error. The Galileo API encountered an internal error. " - "Please try again later or contact support if the issue persists.", - ) +from splunk_ao.exceptions import * # noqa: F403 diff --git a/src/galileo/handlers/agent_control/__init__.py b/src/galileo/handlers/agent_control/__init__.py deleted file mode 100644 index e6583508..00000000 --- a/src/galileo/handlers/agent_control/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Agent Control bridge for Galileo logger-backed control span ingestion. - -For Agent Control target resolution, use ``galileo.agent_control``. -""" - -from galileo.handlers.agent_control.bridge import SplunkAOAgentControlBridge, setup_agent_control_bridge - -__all__ = ["SplunkAOAgentControlBridge", "setup_agent_control_bridge"] diff --git a/src/galileo/handlers/langchain/__init__.py b/src/galileo/handlers/langchain/__init__.py deleted file mode 100644 index a427ce81..00000000 --- a/src/galileo/handlers/langchain/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from galileo.handlers.langchain.async_handler import SplunkAOAsyncCallback -from galileo.handlers.langchain.handler import SplunkAOCallback - -__all__ = ("SplunkAOAsyncCallback", "SplunkAOCallback") diff --git a/src/galileo/handlers/openai_agents/__init__.py b/src/galileo/handlers/openai_agents/__init__.py deleted file mode 100644 index c3e006b9..00000000 --- a/src/galileo/handlers/openai_agents/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from galileo.handlers.openai_agents.handler import SplunkAOTracingProcessor - -__all__ = ["SplunkAOTracingProcessor"] diff --git a/src/galileo/schema/__init__.py b/src/galileo/schema/__init__.py deleted file mode 100644 index 76d2ca43..00000000 --- a/src/galileo/schema/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# ruff: noqa: F401 -from galileo.schema.content_blocks import DataContentBlock, IngestContentBlock, IngestMessageContent, TextContentBlock -from galileo.schema.logged import ( - IngestInputType, - IngestOutputType, - LoggedAgentSpan, - LoggedControlSpan, - LoggedLlmSpan, - LoggedSpan, - LoggedTrace, - LoggedWorkflowSpan, - TextOrContentBlocks, -) -from galileo.schema.message import LoggedMessage diff --git a/src/galileo/utils/__init__.py b/src/galileo/utils/__init__.py index 4cc0e5fe..7ad2f533 100644 --- a/src/galileo/utils/__init__.py +++ b/src/galileo/utils/__init__.py @@ -1,9 +1 @@ -from datetime import datetime, timezone - - -def _get_timestamp() -> datetime: - return datetime.now(timezone.utc) - - -def _now_ns() -> int: - return round(_get_timestamp().timestamp() * 1e9) +"""Generated-resource compatibility package for legacy ``galileo.utils`` imports.""" diff --git a/src/galileo/utils/headers_data.py b/src/galileo/utils/headers_data.py index bd361e87..70083047 100644 --- a/src/galileo/utils/headers_data.py +++ b/src/galileo/utils/headers_data.py @@ -1,72 +1,3 @@ -import inspect -from importlib.metadata import PackageNotFoundError, version -from typing import Any +"""Generated-resource compatibility exports for legacy ``galileo.utils.headers_data`` imports.""" - -def get_package_version() -> str: - """Get the package version of galileo.""" - try: - return version("galileo") - except PackageNotFoundError: - return "0.0.0" # Unknown version - - -def get_method_name() -> str: - """Get the entry point method name into the galileo package. - - Returns the last function before exiting the galileo package when - traversing from the bottom of the call stack. This captures any entry - point including direct usage of autogenerated resources or utils. - - Returns - ------- - str - A string in format "{function_name}@{module_name}" or empty string if not found. - """ - frame = inspect.currentframe() - try: - # Collect all frames - frames_info: list[dict[str, Any]] = [] - temp_frame = frame - while temp_frame is not None: - module = inspect.getmodule(temp_frame) - module_name: str = module.__name__ if module else "" - function_name: str = temp_frame.f_code.co_name - filename: str = temp_frame.f_code.co_filename - lineno: int = temp_frame.f_lineno - - frames_info.append({"module": module_name, "function": function_name, "file": filename, "line": lineno}) - temp_frame = temp_frame.f_back - - # Find the entry point into galileo package (traversing from bottom to top) - entry_point: dict[str, Any] | None = None - for i in range(len(frames_info) - 1, -1, -1): - frame_info = frames_info[i] - module_name = str(frame_info["module"]) # Explicitly cast to string - - # Check if this frame is from the galileo package - # Include ALL galileo.* modules (resources, utils, etc.) - if module_name.startswith("galileo."): - entry_point = frame_info - break - - # Return the formatted method name - if entry_point: - return f"{entry_point['function']}@{entry_point['module']}" - - return "" - finally: - # Clean up frame references to avoid reference cycles - del frame - - -def get_sdk_header() -> str: - """Build the X-Galileo-SDK header value.""" - version = get_package_version() - method_name = get_method_name() - - sdk_header = f"galileo-python/{version}" - if method_name: - sdk_header = f"{sdk_header} {method_name}" - - return sdk_header +from splunk_ao.utils.headers_data import * # noqa: F403 diff --git a/src/galileo/README_API_CLIENT.md b/src/splunk_ao/README_API_CLIENT.md similarity index 93% rename from src/galileo/README_API_CLIENT.md rename to src/splunk_ao/README_API_CLIENT.md index d078b7fc..d75991d5 100644 --- a/src/galileo/README_API_CLIENT.md +++ b/src/splunk_ao/README_API_CLIENT.md @@ -7,7 +7,7 @@ A client library for accessing the Galileo platform API First, create a client: ```python -from galileo.api_client import GalileoApiClient +from splunk_ao.api_client import GalileoApiClient # Make sure you've set the SPLUNK_AO_CONSOLE_URL and SPLUNK_AO_API_KEY env vars # Optionally, you can specify both base_url and api_key @@ -63,14 +63,14 @@ Things to know: 1. All path/query params, and bodies become method arguments. 1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) -1. Any endpoint which did not have a tag will be in `galileo.api.default` +1. Any endpoint which did not have a tag will be in `splunk_ao.api.default` ## Advanced customizations There are more settings on the `GalileoApiClient` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case): ```python -from galileo.api_client import GalileoApiClient +from splunk_ao.api_client import GalileoApiClient def log_request(request): print(f"Request event hook: {request.method} {request.url} - Waiting for response") @@ -90,7 +90,7 @@ You can even set the httpx client directly, but beware that this will override a ```python import httpx -from galileo.api_client import GalileoApiClient +from splunk_ao.api_client import GalileoApiClient client = GalileoApiClient() # Note that base_url needs to be re-set, as would any shared cookies, headers, etc. diff --git a/src/galileo/__future__/__init__.py b/src/splunk_ao/__future__/__init__.py similarity index 54% rename from src/galileo/__future__/__init__.py rename to src/splunk_ao/__future__/__init__.py index 33955989..0d50ff2a 100644 --- a/src/galileo/__future__/__init__.py +++ b/src/splunk_ao/__future__/__init__.py @@ -1,28 +1,28 @@ from __future__ import annotations -from galileo.collaborator import Collaborator, CollaboratorRole -from galileo.configuration import Configuration -from galileo.dataset import Dataset -from galileo.experiment import Experiment -from galileo.integration import Integration -from galileo.log_stream import LogStream -from galileo.metric import CodeMetric, SplunkAOMetric, LlmMetric, LocalMetric, Metric -from galileo.model import Model -from galileo.project import Project -from galileo.prompt import Prompt -from galileo.schema.message import Message -from galileo.search import RecordType -from galileo.shared.exceptions import ( +from galileo_core.schemas.logging.llm import MessageRole +from galileo_core.schemas.logging.step import StepType +from splunk_ao.collaborator import Collaborator, CollaboratorRole +from splunk_ao.configuration import Configuration +from splunk_ao.dataset import Dataset +from splunk_ao.experiment import Experiment +from splunk_ao.integration import Integration +from splunk_ao.log_stream import LogStream +from splunk_ao.metric import CodeMetric, LlmMetric, LocalMetric, Metric, SplunkAOMetric +from splunk_ao.model import Model +from splunk_ao.project import Project +from splunk_ao.prompt import Prompt +from splunk_ao.schema.message import Message +from splunk_ao.search import RecordType +from splunk_ao.shared.exceptions import ( APIError, ConfigurationError, - SplunkAOFutureError, ResourceConflictError, ResourceNotFoundError, + SplunkAOFutureError, ValidationError, ) -from galileo.utils.log_config import enable_console_logging -from galileo_core.schemas.logging.llm import MessageRole -from galileo_core.schemas.logging.step import StepType +from splunk_ao.utils.log_config import enable_console_logging __all__ = [ "APIError", @@ -33,8 +33,6 @@ "ConfigurationError", "Dataset", "Experiment", - "SplunkAOFutureError", - "SplunkAOMetric", "Integration", "LlmMetric", "LocalMetric", @@ -48,6 +46,8 @@ "RecordType", "ResourceConflictError", "ResourceNotFoundError", + "SplunkAOFutureError", + "SplunkAOMetric", "StepType", "ValidationError", "enable_console_logging", diff --git a/src/splunk_ao/__future__/collaborator.py b/src/splunk_ao/__future__/collaborator.py new file mode 100644 index 00000000..0f0f3606 --- /dev/null +++ b/src/splunk_ao/__future__/collaborator.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.collaborator instead of splunk_ao.__future__.collaborator.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.collaborator is deprecated. Use splunk_ao.collaborator instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.collaborator import Collaborator, CollaboratorRole # noqa: E402 + +__all__ = ["Collaborator", "CollaboratorRole"] diff --git a/src/galileo/__future__/configuration.py b/src/splunk_ao/__future__/configuration.py similarity index 60% rename from src/galileo/__future__/configuration.py rename to src/splunk_ao/__future__/configuration.py index 60d9a992..808c4ee6 100644 --- a/src/galileo/__future__/configuration.py +++ b/src/splunk_ao/__future__/configuration.py @@ -1,14 +1,14 @@ -"""Deprecated: use galileo.configuration instead of galileo.__future__.configuration.""" +"""Deprecated: use splunk_ao.configuration instead of splunk_ao.__future__.configuration.""" import warnings warnings.warn( - "Importing from galileo.__future__.configuration is deprecated. Use galileo.configuration instead.", + "Importing from splunk_ao.__future__.configuration is deprecated. Use splunk_ao.configuration instead.", DeprecationWarning, stacklevel=2, ) -from galileo.configuration import ( # noqa: E402 +from splunk_ao.configuration import ( # noqa: E402 _CONFIGURATION_KEYS, _KEYS_BY_NAME, VALID_LOG_LEVELS, diff --git a/src/splunk_ao/__future__/dataset.py b/src/splunk_ao/__future__/dataset.py new file mode 100644 index 00000000..ec96699e --- /dev/null +++ b/src/splunk_ao/__future__/dataset.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.dataset instead of splunk_ao.__future__.dataset.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.dataset is deprecated. Use splunk_ao.dataset instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.dataset import Dataset # noqa: E402 + +__all__ = ["Dataset"] diff --git a/src/splunk_ao/__future__/experiment.py b/src/splunk_ao/__future__/experiment.py new file mode 100644 index 00000000..ee8ca8e5 --- /dev/null +++ b/src/splunk_ao/__future__/experiment.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.experiment instead of splunk_ao.__future__.experiment.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.experiment is deprecated. Use splunk_ao.experiment instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.experiment import Experiment # noqa: E402 + +__all__ = ["Experiment"] diff --git a/src/splunk_ao/__future__/integration.py b/src/splunk_ao/__future__/integration.py new file mode 100644 index 00000000..e76c3e31 --- /dev/null +++ b/src/splunk_ao/__future__/integration.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.integration instead of splunk_ao.__future__.integration.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.integration is deprecated. Use splunk_ao.integration instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.integration import Integration # noqa: E402 + +__all__ = ["Integration"] diff --git a/src/splunk_ao/__future__/log_stream.py b/src/splunk_ao/__future__/log_stream.py new file mode 100644 index 00000000..5c090f22 --- /dev/null +++ b/src/splunk_ao/__future__/log_stream.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.log_stream instead of splunk_ao.__future__.log_stream.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.log_stream is deprecated. Use splunk_ao.log_stream instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.log_stream import LogStream # noqa: E402 + +__all__ = ["LogStream"] diff --git a/src/splunk_ao/__future__/metric.py b/src/splunk_ao/__future__/metric.py new file mode 100644 index 00000000..3df9a658 --- /dev/null +++ b/src/splunk_ao/__future__/metric.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.metric instead of splunk_ao.__future__.metric.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.metric is deprecated. Use splunk_ao.metric instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.metric import BuiltInMetrics, CodeMetric, LlmMetric, LocalMetric, Metric, SplunkAOMetric # noqa: E402 + +__all__ = ["BuiltInMetrics", "CodeMetric", "LlmMetric", "LocalMetric", "Metric", "SplunkAOMetric"] diff --git a/src/splunk_ao/__future__/model.py b/src/splunk_ao/__future__/model.py new file mode 100644 index 00000000..ad4b9276 --- /dev/null +++ b/src/splunk_ao/__future__/model.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.model instead of splunk_ao.__future__.model.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.model is deprecated. Use splunk_ao.model instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.model import Model # noqa: E402 + +__all__ = ["Model"] diff --git a/src/splunk_ao/__future__/project.py b/src/splunk_ao/__future__/project.py new file mode 100644 index 00000000..4ce7c528 --- /dev/null +++ b/src/splunk_ao/__future__/project.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.project instead of splunk_ao.__future__.project.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.project is deprecated. Use splunk_ao.project instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.project import Project # noqa: E402 + +__all__ = ["Project"] diff --git a/src/splunk_ao/__future__/prompt.py b/src/splunk_ao/__future__/prompt.py new file mode 100644 index 00000000..e1b9fc5c --- /dev/null +++ b/src/splunk_ao/__future__/prompt.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.prompt instead of splunk_ao.__future__.prompt.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.prompt is deprecated. Use splunk_ao.prompt instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.prompt import Prompt, PromptVersion, _parse_template_to_messages # noqa: E402 + +__all__ = ["Prompt", "PromptVersion", "_parse_template_to_messages"] diff --git a/src/galileo/__future__/provider.py b/src/splunk_ao/__future__/provider.py similarity index 64% rename from src/galileo/__future__/provider.py rename to src/splunk_ao/__future__/provider.py index 777ef851..a7a08972 100644 --- a/src/galileo/__future__/provider.py +++ b/src/splunk_ao/__future__/provider.py @@ -1,14 +1,14 @@ -"""Deprecated: use galileo.provider instead of galileo.__future__.provider.""" +"""Deprecated: use splunk_ao.provider instead of splunk_ao.__future__.provider.""" import warnings warnings.warn( - "Importing from galileo.__future__.provider is deprecated. Use galileo.provider instead.", + "Importing from splunk_ao.__future__.provider is deprecated. Use splunk_ao.provider instead.", DeprecationWarning, stacklevel=2, ) -from galileo.provider import ( # noqa: E402 +from splunk_ao.provider import ( # noqa: E402 AnthropicProvider, AzureProvider, BedrockProvider, diff --git a/src/splunk_ao/__future__/shared/__init__.py b/src/splunk_ao/__future__/shared/__init__.py new file mode 100644 index 00000000..8a0445f7 --- /dev/null +++ b/src/splunk_ao/__future__/shared/__init__.py @@ -0,0 +1,6 @@ +"""Re-export from splunk_ao.shared — will be deprecated once all __future__ modules are migrated.""" + +from splunk_ao.shared.filter import boolean, date, number, text +from splunk_ao.shared.sort import sort + +__all__ = ["boolean", "date", "number", "sort", "text"] diff --git a/src/splunk_ao/__future__/shared/base.py b/src/splunk_ao/__future__/shared/base.py new file mode 100644 index 00000000..53c17ce8 --- /dev/null +++ b/src/splunk_ao/__future__/shared/base.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.shared.base instead of splunk_ao.__future__.shared.base.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.base is deprecated. Use splunk_ao.shared.base instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.base import StateManagementMixin, SyncState # noqa: E402 + +__all__ = ["StateManagementMixin", "SyncState"] diff --git a/src/splunk_ao/__future__/shared/column.py b/src/splunk_ao/__future__/shared/column.py new file mode 100644 index 00000000..e324d470 --- /dev/null +++ b/src/splunk_ao/__future__/shared/column.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.shared.column instead of splunk_ao.__future__.shared.column.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.column is deprecated. Use splunk_ao.shared.column instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.column import Column, ColumnCollection, _unwrap_unset # noqa: E402 + +__all__ = ["Column", "ColumnCollection", "_unwrap_unset"] diff --git a/src/galileo/__future__/shared/exceptions.py b/src/splunk_ao/__future__/shared/exceptions.py similarity index 63% rename from src/galileo/__future__/shared/exceptions.py rename to src/splunk_ao/__future__/shared/exceptions.py index aa01401a..41c33ed1 100644 --- a/src/galileo/__future__/shared/exceptions.py +++ b/src/splunk_ao/__future__/shared/exceptions.py @@ -1,20 +1,20 @@ -"""Deprecated: use galileo.shared.exceptions instead of galileo.__future__.shared.exceptions.""" +"""Deprecated: use splunk_ao.shared.exceptions instead of splunk_ao.__future__.shared.exceptions.""" import warnings warnings.warn( - "Importing from galileo.__future__.shared.exceptions is deprecated. Use galileo.shared.exceptions instead.", + "Importing from splunk_ao.__future__.shared.exceptions is deprecated. Use splunk_ao.shared.exceptions instead.", DeprecationWarning, stacklevel=2, ) -from galileo.shared.exceptions import ( # noqa: E402 +from splunk_ao.shared.exceptions import ( # noqa: E402 APIError, ConfigurationError, - SplunkAOFutureError, IntegrationNotConfiguredError, ResourceConflictError, ResourceNotFoundError, + SplunkAOFutureError, SyncError, ValidationError, ) @@ -22,10 +22,10 @@ __all__ = [ "APIError", "ConfigurationError", - "SplunkAOFutureError", "IntegrationNotConfiguredError", "ResourceConflictError", "ResourceNotFoundError", + "SplunkAOFutureError", "SyncError", "ValidationError", ] diff --git a/src/splunk_ao/__future__/shared/experiment_result.py b/src/splunk_ao/__future__/shared/experiment_result.py new file mode 100644 index 00000000..cb0e623a --- /dev/null +++ b/src/splunk_ao/__future__/shared/experiment_result.py @@ -0,0 +1,18 @@ +"""Deprecated: use splunk_ao.shared.experiment_result instead of splunk_ao.__future__.shared.experiment_result.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.experiment_result is deprecated. " + "Use splunk_ao.shared.experiment_result instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.experiment_result import ( # noqa: E402 + ExperimentPhaseInfo, + ExperimentRunResult, + ExperimentStatusInfo, +) + +__all__ = ["ExperimentPhaseInfo", "ExperimentRunResult", "ExperimentStatusInfo"] diff --git a/src/galileo/__future__/shared/filter.py b/src/splunk_ao/__future__/shared/filter.py similarity index 56% rename from src/galileo/__future__/shared/filter.py rename to src/splunk_ao/__future__/shared/filter.py index 0045fe52..25e969b0 100644 --- a/src/galileo/__future__/shared/filter.py +++ b/src/splunk_ao/__future__/shared/filter.py @@ -1,14 +1,14 @@ -"""Deprecated: use galileo.shared.filter instead of galileo.__future__.shared.filter.""" +"""Deprecated: use splunk_ao.shared.filter instead of splunk_ao.__future__.shared.filter.""" import warnings warnings.warn( - "Importing from galileo.__future__.shared.filter is deprecated. Use galileo.shared.filter instead.", + "Importing from splunk_ao.__future__.shared.filter is deprecated. Use splunk_ao.shared.filter instead.", DeprecationWarning, stacklevel=2, ) -from galileo.shared.filter import ( # noqa: E402 +from splunk_ao.shared.filter import ( # noqa: E402 BooleanFilter, DateFilter, Filter, diff --git a/src/splunk_ao/__future__/shared/query_result.py b/src/splunk_ao/__future__/shared/query_result.py new file mode 100644 index 00000000..9e685c7a --- /dev/null +++ b/src/splunk_ao/__future__/shared/query_result.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.shared.query_result instead of splunk_ao.__future__.shared.query_result.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.query_result is deprecated. Use splunk_ao.shared.query_result instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.query_result import QueryResult, _flatten_dict # noqa: E402 + +__all__ = ["QueryResult", "_flatten_dict"] diff --git a/src/splunk_ao/__future__/shared/sort.py b/src/splunk_ao/__future__/shared/sort.py new file mode 100644 index 00000000..f36b148a --- /dev/null +++ b/src/splunk_ao/__future__/shared/sort.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.shared.sort instead of splunk_ao.__future__.shared.sort.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.sort is deprecated. Use splunk_ao.shared.sort instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.sort import Sort, sort # noqa: E402 + +__all__ = ["Sort", "sort"] diff --git a/src/splunk_ao/__future__/shared/utils.py b/src/splunk_ao/__future__/shared/utils.py new file mode 100644 index 00000000..174fb15a --- /dev/null +++ b/src/splunk_ao/__future__/shared/utils.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.shared.utils instead of splunk_ao.__future__.shared.utils.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.shared.utils is deprecated. Use splunk_ao.shared.utils instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.shared.utils import classproperty # noqa: E402 + +__all__ = ["classproperty"] diff --git a/src/splunk_ao/__future__/types.py b/src/splunk_ao/__future__/types.py new file mode 100644 index 00000000..1081162d --- /dev/null +++ b/src/splunk_ao/__future__/types.py @@ -0,0 +1,13 @@ +"""Deprecated: use splunk_ao.types instead of splunk_ao.__future__.types.""" + +import warnings + +warnings.warn( + "Importing from splunk_ao.__future__.types is deprecated. Use splunk_ao.types instead.", + DeprecationWarning, + stacklevel=2, +) + +from splunk_ao.types import MetricSpec # noqa: E402 + +__all__ = ["MetricSpec"] diff --git a/src/splunk_ao/__init__.py b/src/splunk_ao/__init__.py new file mode 100644 index 00000000..f5b2e36e --- /dev/null +++ b/src/splunk_ao/__init__.py @@ -0,0 +1,173 @@ +"""Splunk AO.""" + +# ruff: noqa: E402 + +import sys + +vars(sys)["_splunk_ao_suppress_galileo_deprecation_warning"] = True + +from galileo.resources.models.document import Document +from galileo_core.helpers.api_key import create_api_key, delete_api_key, list_api_keys +from galileo_core.helpers.dependencies import is_dependency_available +from galileo_core.schemas.logging.llm import MessageRole, ToolCall, ToolCallFunction +from galileo_core.schemas.logging.session import Session +from galileo_core.schemas.logging.span import ( + AgentSpan, + LlmSpan, + RetrieverSpan, + Span, + StepWithChildSpans, + ToolSpan, + WorkflowSpan, +) +from galileo_core.schemas.logging.step import StepType +from galileo_core.schemas.logging.trace import Trace +from galileo_core.schemas.protect.execution_status import ExecutionStatus +from galileo_core.schemas.protect.payload import Payload +from galileo_core.schemas.protect.request import Request +from galileo_core.schemas.protect.response import Response +from galileo_core.schemas.protect.ruleset import Ruleset +from galileo_core.schemas.protect.stage import StageType +from splunk_ao.agent_control import AgentControlTarget, AgentControlTargetUnresolvedError, get_agent_control_target +from splunk_ao.collaborator import Collaborator, CollaboratorRole +from splunk_ao.configuration import Configuration +from splunk_ao.dataset import Dataset +from splunk_ao.decorator import SplunkAODecorator, galileo_context, log, start_session +from splunk_ao.exceptions import ( + AuthenticationError, + BadRequestError, + ConflictError, + ForbiddenError, + NotFoundError, + RateLimitError, + ServerError, + SplunkAOAPIError, + SplunkAOLoggerException, +) +from splunk_ao.experiment import Experiment +from splunk_ao.handlers.agent_control import SplunkAOAgentControlBridge, setup_agent_control_bridge +from splunk_ao.integration import Integration +from splunk_ao.log_stream import LogStream +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult, ControlSpan +from splunk_ao.metric import CodeMetric, LlmMetric, LocalMetric, Metric, SplunkAOMetric +from splunk_ao.model import Model +from splunk_ao.project import Project +from splunk_ao.prompt import Prompt +from splunk_ao.protect import ainvoke_protect, invoke_protect +from splunk_ao.provider import AnthropicProvider, AzureProvider, BedrockProvider, OpenAIProvider, Provider +from splunk_ao.schema.message import Message +from splunk_ao.schema.metrics import GalileoScorers, SplunkAOMetrics +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.exceptions import ( + APIError, + ConfigurationError, + ResourceConflictError, + ResourceNotFoundError, + SplunkAOFutureError, + ValidationError, +) +from splunk_ao.stages import ( + create_protect_stage, + get_protect_stage, + pause_protect_stage, + resume_protect_stage, + update_protect_stage, +) +from splunk_ao.tracing import get_tracing_headers +from splunk_ao.types import MetricSpec +from splunk_ao.utils.log_config import enable_console_logging + +vars(sys)["_splunk_ao_suppress_galileo_deprecation_warning"] = False + +__version__ = "2.3.0" + +__all__ = [ + "APIError", + "AgentControlTarget", + "AgentControlTargetUnresolvedError", + "AgentSpan", + "AnthropicProvider", + "AuthenticationError", + "AzureProvider", + "BadRequestError", + "BedrockProvider", + "CodeMetric", + "Collaborator", + "CollaboratorRole", + "Configuration", + "ConfigurationError", + "ConflictError", + "ControlAppliesTo", + "ControlCheckStage", + "ControlResult", + "ControlSpan", + "Dataset", + "Document", + "ExecutionStatus", + "Experiment", + "ForbiddenError", + "GalileoScorers", + "Integration", + "LlmMetric", + "LlmSpan", + "LocalMetric", + "LogStream", + "Message", + "MessageRole", + "Metric", + "MetricSpec", + "Model", + "NotFoundError", + "OpenAIProvider", + "Payload", + "Project", + "Prompt", + "Provider", + "RateLimitError", + "Request", + "ResourceConflictError", + "ResourceNotFoundError", + "Response", + "RetrieverSpan", + "Ruleset", + "ServerError", + "Session", + "Span", + "SplunkAOAPIError", + "SplunkAOAgentControlBridge", + "SplunkAODecorator", + "SplunkAOFutureError", + "SplunkAOLogger", + "SplunkAOLoggerException", + "SplunkAOMetric", + "SplunkAOMetrics", + "StageType", + "StepType", + "StepWithChildSpans", + "SyncState", + "ToolCall", + "ToolCallFunction", + "ToolSpan", + "Trace", + "ValidationError", + "WorkflowSpan", + "ainvoke_protect", + "create_api_key", + "create_protect_stage", + "delete_api_key", + "enable_console_logging", + "galileo_context", + "get_agent_control_target", + "get_protect_stage", + "get_tracing_headers", + "invoke_protect", + "is_dependency_available", + "list_api_keys", + "log", + "pause_protect_stage", + "resume_protect_stage", + "setup_agent_control_bridge", + "start_session", + "update_protect_stage", +] diff --git a/src/galileo/agent_control.py b/src/splunk_ao/agent_control.py similarity index 95% rename from src/galileo/agent_control.py rename to src/splunk_ao/agent_control.py index df703bea..0f97fe2c 100644 --- a/src/galileo/agent_control.py +++ b/src/splunk_ao/agent_control.py @@ -3,7 +3,7 @@ This module produces generic Agent Control targets from Galileo state. It does not import the Agent Control SDK; callers wire the two SDKs together explicitly. -For Agent Control telemetry ingestion, use ``galileo.handlers.agent_control``. +For Agent Control telemetry ingestion, use ``splunk_ao.handlers.agent_control``. """ from __future__ import annotations @@ -13,9 +13,9 @@ from dataclasses import dataclass from uuid import UUID -from galileo.decorator import galileo_context -from galileo.utils.env_helpers import _get_log_stream_or_default, _get_project_or_default -from galileo.utils.singleton import SplunkAOLoggerSingleton +from splunk_ao.decorator import galileo_context +from splunk_ao.utils.env_helpers import _get_log_stream_or_default, _get_project_or_default +from splunk_ao.utils.singleton import SplunkAOLoggerSingleton LOG_STREAM_TARGET_TYPE = "log_stream" diff --git a/src/galileo/collaborator.py b/src/splunk_ao/collaborator.py similarity index 99% rename from src/galileo/collaborator.py rename to src/splunk_ao/collaborator.py index c348729a..a60d1573 100644 --- a/src/galileo/collaborator.py +++ b/src/splunk_ao/collaborator.py @@ -4,10 +4,9 @@ from datetime import datetime from typing import Any -from galileo.projects import Projects - # Re-export CollaboratorRole from the auto-generated models from galileo.resources.models.collaborator_role import CollaboratorRole +from splunk_ao.projects import Projects logger = logging.getLogger(__name__) @@ -52,7 +51,7 @@ class Collaborator: print(f"User has {viewer.role} access") # Filter by role using the CollaboratorRole enum - from galileo import CollaboratorRole + from splunk_ao import CollaboratorRole editors = [c for c in collaborators if c.role == CollaboratorRole.EDITOR] # Update a collaborator's role directly on the object diff --git a/src/galileo/config.py b/src/splunk_ao/config.py similarity index 98% rename from src/galileo/config.py rename to src/splunk_ao/config.py index 6819ae8b..7e1fd778 100644 --- a/src/galileo/config.py +++ b/src/splunk_ao/config.py @@ -5,9 +5,9 @@ from pydantic_core import Url -from galileo.constants import DEFAULT_CONSOLE_URL -from galileo.shared.exceptions import ConfigurationError from galileo_core.schemas.base_config import GalileoConfig +from splunk_ao.constants import DEFAULT_CONSOLE_URL +from splunk_ao.shared.exceptions import ConfigurationError class SplunkAOConfig(GalileoConfig): diff --git a/src/galileo/configuration.py b/src/splunk_ao/configuration.py similarity index 98% rename from src/galileo/configuration.py rename to src/splunk_ao/configuration.py index b0e9c316..38b220d1 100644 --- a/src/galileo/configuration.py +++ b/src/splunk_ao/configuration.py @@ -6,11 +6,11 @@ from pathlib import Path from typing import Any -from galileo.config import SplunkAOConfig -from galileo.constants import DEFAULT_CONSOLE_URL -from galileo.shared.exceptions import ConfigurationError -from galileo.utils.log_config import enable_console_logging as _enable_console_logging -from galileo.utils.log_config import get_logger +from splunk_ao.config import SplunkAOConfig +from splunk_ao.constants import DEFAULT_CONSOLE_URL +from splunk_ao.shared.exceptions import ConfigurationError +from splunk_ao.utils.log_config import SDK_LOGGER_NAME, get_logger +from splunk_ao.utils.log_config import enable_console_logging as _enable_console_logging logger = get_logger(__name__) @@ -502,7 +502,7 @@ def disable_console_logging(cls) -> None: Configuration.disable_console_logging() ``` """ - galileo_logger = logging.getLogger("galileo") + galileo_logger = logging.getLogger(SDK_LOGGER_NAME) # Remove all stream handlers for handler in galileo_logger.handlers[:]: diff --git a/src/galileo/constants/__init__.py b/src/splunk_ao/constants/__init__.py similarity index 100% rename from src/galileo/constants/__init__.py rename to src/splunk_ao/constants/__init__.py diff --git a/src/galileo/constants/protect.py b/src/splunk_ao/constants/protect.py similarity index 100% rename from src/galileo/constants/protect.py rename to src/splunk_ao/constants/protect.py diff --git a/src/galileo/constants/routes.py b/src/splunk_ao/constants/routes.py similarity index 100% rename from src/galileo/constants/routes.py rename to src/splunk_ao/constants/routes.py diff --git a/src/galileo/constants/tracing.py b/src/splunk_ao/constants/tracing.py similarity index 84% rename from src/galileo/constants/tracing.py rename to src/splunk_ao/constants/tracing.py index 29f971f2..91ab3a7e 100644 --- a/src/galileo/constants/tracing.py +++ b/src/splunk_ao/constants/tracing.py @@ -1,6 +1,6 @@ """Constants for distributed tracing.""" -from galileo.constants import GALILEO_HEADER_PREFIX +from splunk_ao.constants import GALILEO_HEADER_PREFIX # HTTP header names for propagating distributed tracing context # These headers follow the pattern of namespaced custom headers (X-Galileo-*) diff --git a/src/galileo/dataset.py b/src/splunk_ao/dataset.py similarity index 99% rename from src/galileo/dataset.py rename to src/splunk_ao/dataset.py index 918753b1..c7bd4281 100644 --- a/src/galileo/dataset.py +++ b/src/splunk_ao/dataset.py @@ -4,14 +4,14 @@ from datetime import datetime from typing import Any, TypeAlias -from galileo.datasets import Datasets from galileo.resources.models.dataset_content import DatasetContent from galileo.resources.models.dataset_row import DatasetRow from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.list_dataset_version_response import ListDatasetVersionResponse from galileo.resources.types import Unset -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError +from splunk_ao.datasets import Datasets +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError #: Type alias for clarity: ``get_version_content`` returns the content of a specific #: dataset version. The underlying auto-generated type is ``DatasetContent``. diff --git a/src/galileo/datasets.py b/src/splunk_ao/datasets.py similarity index 99% rename from src/galileo/datasets.py rename to src/splunk_ao/datasets.py index 36200c15..96ea2209 100644 --- a/src/galileo/datasets.py +++ b/src/splunk_ao/datasets.py @@ -3,7 +3,6 @@ import time from typing import Any, overload -from galileo.config import SplunkAOConfig from galileo.resources.api.datasets import ( create_dataset_datasets_post, delete_dataset_datasets_dataset_id_delete, @@ -41,12 +40,13 @@ from galileo.resources.models.update_dataset_content_request import UpdateDatasetContentRequest from galileo.resources.models.update_dataset_request import UpdateDatasetRequest from galileo.resources.types import UNSET, File, Unset -from galileo.schema.datasets import DatasetRecord -from galileo.utils.datasets import normalize_dataset_rows, remap_output_to_ground_truth, validate_dataset_in_project -from galileo.utils.exceptions import APIException -from galileo.utils.log_config import get_logger -from galileo.utils.projects import resolve_project_id from galileo_core.utils.dataset import DatasetType, parse_dataset +from splunk_ao.config import SplunkAOConfig +from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.utils.datasets import normalize_dataset_rows, remap_output_to_ground_truth, validate_dataset_in_project +from splunk_ao.utils.exceptions import APIException +from splunk_ao.utils.log_config import get_logger +from splunk_ao.utils.projects import resolve_project_id logger = get_logger(__name__) MAX_DATASET_ROWS = 100000 diff --git a/src/galileo/decorator.py b/src/splunk_ao/decorator.py similarity index 98% rename from src/galileo/decorator.py rename to src/splunk_ao/decorator.py index 4dceeba5..dab7aefa 100644 --- a/src/galileo/decorator.py +++ b/src/splunk_ao/decorator.py @@ -8,7 +8,7 @@ 1. Basic usage - decorate any function to log its execution: ```python - from galileo import log + from splunk_ao import log @log def my_function(arg1, arg2): @@ -29,7 +29,7 @@ def call_llm(prompt, temperature=0.7): 3. Using context manager for grouping related operations: ```python - from galileo import galileo_context + from splunk_ao import galileo_context with galileo_context(project="my-project", log_stream="production"): result1 = my_function() @@ -56,21 +56,21 @@ def call_llm(prompt, temperature=0.7): from typing_extensions import ParamSpec -from galileo.constants import LoggerModeType -from galileo.logger import SplunkAOLogger -from galileo.logger.logger import STUB_TRACE_NAME -from galileo.schema.content_blocks import is_content_block_list -from galileo.schema.datasets import DatasetRecord -from galileo.schema.metrics import LocalMetricConfig -from galileo.schema.trace import SPAN_TYPE -from galileo.shared.exceptions import ConfigurationError -from galileo.utils import _get_timestamp -from galileo.utils.env_helpers import _get_mode_or_default -from galileo.utils.serialization import EventSerializer, convert_time_delta_to_ns, serialize_to_str -from galileo.utils.singleton import SplunkAOLoggerSingleton -from galileo.utils.span_utils import is_concludable_span_type, is_textual_span_type from galileo_core.schemas.logging.span import WorkflowSpan from galileo_core.schemas.logging.trace import Trace +from splunk_ao.constants import LoggerModeType +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.logger.logger import STUB_TRACE_NAME +from splunk_ao.schema.content_blocks import is_content_block_list +from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.schema.metrics import LocalMetricConfig +from splunk_ao.schema.trace import SPAN_TYPE +from splunk_ao.shared.exceptions import ConfigurationError +from splunk_ao.utils import _get_timestamp +from splunk_ao.utils.env_helpers import _get_mode_or_default +from splunk_ao.utils.serialization import EventSerializer, convert_time_delta_to_ns, serialize_to_str +from splunk_ao.utils.singleton import SplunkAOLoggerSingleton +from splunk_ao.utils.span_utils import is_concludable_span_type, is_textual_span_type _logger = logging.getLogger(__name__) @@ -1112,7 +1112,7 @@ def flush( """ # Build a wrapper that logs via this module's logger (so callers can patch - # "galileo.decorator._logger") and then forwards to the user callback. + # "splunk_ao.decorator._logger") and then forwards to the user callback. def _on_flush_error(exc: Exception) -> None: if on_error is not None: _logger.debug(f"Galileo flush failed, continuing without flushing: {exc}") @@ -1315,7 +1315,7 @@ def galileo_dataset_context( Examples -------- - >>> from galileo.decorator import galileo_dataset_context + >>> from splunk_ao.decorator import galileo_dataset_context >>> >>> # Set ground truth for a single agent call >>> with galileo_dataset_context( diff --git a/src/splunk_ao/exceptions.py b/src/splunk_ao/exceptions.py new file mode 100644 index 00000000..c7e04277 --- /dev/null +++ b/src/splunk_ao/exceptions.py @@ -0,0 +1,174 @@ +"""Galileo SDK exceptions.""" + +from typing import Any, overload + +__all__ = [ + "AuthenticationError", + "BadRequestError", + "ConflictError", + "ForbiddenError", + "NotFoundError", + "RateLimitError", + "ServerError", + "SplunkAOAPIError", + "SplunkAOLoggerException", +] + +# Sentinel for "argument not provided" so the message overload of NotFoundError can +# reject _any_ explicit second argument (including ``b""``), not just non-empty bytes. +_UNSET: Any = object() + + +class SplunkAOLoggerException(Exception): + """Exception raised by SplunkAOLogger.""" + + +class SplunkAOAPIError(Exception): + """Base class for Galileo API HTTP errors with actionable messages.""" + + def __init__(self, status_code: int, content: bytes, message: str): + self.status_code = status_code + self.content = content + self.message = message + response_text = content.decode(errors="ignore") + super().__init__(f"{message} (HTTP {status_code})\n\nResponse: {response_text}") + + +class BadRequestError(SplunkAOAPIError): + """HTTP 400 - The request was malformed or invalid.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__(status_code, content, "Bad request. Check your request parameters and body format.") + + +class AuthenticationError(SplunkAOAPIError): + """HTTP 401 - Authentication failed.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__( + status_code, + content, + "Authentication failed. Check your API key is valid and not expired. " + "Set via SPLUNK_AO_API_KEY environment variable or pass api_key= when initializing the client.", + ) + + +class ForbiddenError(SplunkAOAPIError): + """HTTP 403 - Insufficient permissions.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__( + status_code, + content, + "Permission denied. Your API key doesn't have access to this resource. " + "Check your organization and project permissions.", + ) + + +class NotFoundError(SplunkAOAPIError): + r"""HTTP 404 - Resource not found. + + Parameters + ---------- + status_code_or_message : int | str + Either an HTTP status code (``int``, paired with ``content``) or a + full message string (``str``, used on its own). + content : bytes, optional + Raw response body. Only valid alongside an ``int`` status code; on the + message path it must be omitted. + + Notes + ----- + Two construction paths are supported, exposed via ``@overload`` so type + checkers see the right shape per call site: + + - ``NotFoundError(status_code, content)`` — built from an HTTP 404 response + by the generated client. Uses the standard "Resource not found…" message. + - ``NotFoundError(message)`` — built from an SDK-level lookup that has no + HTTP response (e.g. resolving a project from env vars). The string is the + full message; no ``content`` argument is accepted. + + The runtime constructor also enforces the contract. The following all raise + ``TypeError`` instead of producing nonsensical state: + + - Mixing shapes: ``NotFoundError("msg", b"")`` / ``NotFoundError("msg", b"body")`` + - Passing ``None``: ``NotFoundError(None)`` + - Passing ``bool``: ``NotFoundError(True, b"x")`` (``bool`` is technically an + ``int`` subclass but is rejected explicitly to avoid silent acceptance) + + Examples + -------- + >>> NotFoundError(404, b"{\\"detail\\": ...}") # HTTP response path + >>> NotFoundError("Project \\"foo\\" not found.") # SDK lookup path + """ + + @overload + def __init__(self, message: str) -> None: ... + @overload + def __init__(self, status_code: int, content: bytes) -> None: ... + + def __init__(self, status_code_or_message: int | str, content: bytes = _UNSET) -> None: + if isinstance(status_code_or_message, str): + if content is not _UNSET: + raise TypeError( + "NotFoundError(message) does not accept a content argument. " + "Use NotFoundError(status_code, content) for HTTP-style construction." + ) + self.status_code = 404 + self.content = b"" + self.message = status_code_or_message + Exception.__init__(self, status_code_or_message) + # mypy narrows to ``int`` here from the ``int | str`` annotation, so the + # ``not isinstance(..., bool)`` half looks redundant statically — but at + # runtime ``bool`` is an ``int`` subclass, so this guard is real + # protection against callers passing ``True``/``False`` accidentally. + elif isinstance(status_code_or_message, int) and not isinstance( # type: ignore[redundant-expr] + status_code_or_message, bool + ): + super().__init__( + status_code_or_message, + b"" if content is _UNSET else content, + "Resource not found. The requested project, dataset, or resource doesn't exist. " + "Verify the ID or name is correct.", + ) + else: + raise TypeError( + "NotFoundError requires either (status_code: int, content: bytes) " + f"or (message: str); got {type(status_code_or_message).__name__}." + ) + + +class ConflictError(SplunkAOAPIError): + """HTTP 409 - Resource conflict.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__( + status_code, + content, + "Resource conflict. A resource with this name or ID already exists, " + "or the operation conflicts with the current state.", + ) + + +class RateLimitError(SplunkAOAPIError): + """HTTP 429 - Rate limit exceeded.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__( + status_code, + content, + "Rate limit exceeded. Too many requests. Please wait before retrying. " + "Consider adding delays between API calls.", + ) + + +class ServerError(SplunkAOAPIError): + """HTTP 5xx - Server-side error.""" + + def __init__(self, status_code: int, content: bytes): + super().__init__( + status_code, + content, + "Server error. The Galileo API encountered an internal error. " + "Please try again later or contact support if the issue persists.", + ) diff --git a/src/galileo/experiment.py b/src/splunk_ao/experiment.py similarity index 96% rename from src/galileo/experiment.py rename to src/splunk_ao/experiment.py index dd487dcc..669456e6 100644 --- a/src/galileo/experiment.py +++ b/src/splunk_ao/experiment.py @@ -6,15 +6,6 @@ from collections.abc import Iterator from typing import TYPE_CHECKING, Any -from galileo.config import SplunkAOConfig -from galileo.datasets import Dataset as LegacyDataset -from galileo.exceptions import NotFoundError -from galileo.experiment_tags import upsert_experiment_tag -from galileo.experiments import Experiments as ExperimentsService -from galileo.experiments import _default_prompt_settings -from galileo.export import ExportClient -from galileo.job_progress import get_run_scorer_jobs, job_progress -from galileo.prompts import PromptTemplate, get_prompt from galileo.resources.api.experiment import ( delete_experiment_projects_project_id_experiments_experiment_id_delete, experiments_available_columns_projects_project_id_experiments_available_columns_post, @@ -38,30 +29,39 @@ from galileo.resources.models.log_records_available_columns_response import LogRecordsAvailableColumnsResponse from galileo.resources.models.metric_aggregates import MetricAggregates from galileo.resources.types import Unset +from splunk_ao.config import SplunkAOConfig +from splunk_ao.datasets import Dataset as LegacyDataset +from splunk_ao.exceptions import NotFoundError +from splunk_ao.experiment_tags import upsert_experiment_tag +from splunk_ao.experiments import Experiments as ExperimentsService +from splunk_ao.experiments import _default_prompt_settings +from splunk_ao.export import ExportClient +from splunk_ao.job_progress import get_run_scorer_jobs, job_progress +from splunk_ao.prompts import PromptTemplate, get_prompt # TODO: DatasetRecord needed for function-based experiments -# from galileo.schema.datasets import DatasetRecord -from galileo.schema.filters import FilterType -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig, Metric -from galileo.search import RecordType, Search -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import ValidationError -from galileo.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo -from galileo.shared.project_resolver import _resolve_project -from galileo.shared.query_result import QueryResult +# from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.schema.filters import FilterType +from splunk_ao.schema.metrics import LocalMetricConfig, Metric, SplunkAOMetrics +from splunk_ao.search import RecordType, Search +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import ValidationError +from splunk_ao.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo +from splunk_ao.shared.project_resolver import _resolve_project +from splunk_ao.shared.query_result import QueryResult # TODO: get_records_for_dataset needed for function-based experiments -# from galileo.utils.datasets import get_records_for_dataset, load_dataset_and_records -from galileo.utils.datasets import load_dataset_and_records -from galileo.utils.log_config import get_logger -from galileo.utils.metrics import create_metric_configs -from galileo.utils.validations import require_exactly_one +# from splunk_ao.utils.datasets import get_records_for_dataset, load_dataset_and_records +from splunk_ao.utils.datasets import load_dataset_and_records +from splunk_ao.utils.log_config import get_logger +from splunk_ao.utils.metrics import create_metric_configs +from splunk_ao.utils.validations import require_exactly_one if TYPE_CHECKING: - from galileo.dataset import Dataset - from galileo.project import Project - from galileo.prompt import Prompt - from galileo.shared.column import ColumnCollection + from splunk_ao.dataset import Dataset + from splunk_ao.project import Project + from splunk_ao.prompt import Prompt + from splunk_ao.shared.column import ColumnCollection _logger = get_logger(__name__) @@ -303,7 +303,7 @@ def __init__( if model is not None: # Local import to avoid circular dependency - from galileo.model import Model + from splunk_ao.model import Model if isinstance(model, Model): self._model_obj = model @@ -319,7 +319,7 @@ def __init__( # TODO: Improve serialization and delegate the responsibilities to the serializer. if dataset is not None: # Local import to avoid circular dependency - from galileo.dataset import Dataset + from splunk_ao.dataset import Dataset if isinstance(dataset, Dataset): self.dataset_id = dataset.id @@ -346,7 +346,7 @@ def __init__( "'prompt' takes precedence and 'prompt_name' will be ignored." ) # Local import to avoid circular dependency - from galileo.prompt import Prompt + from splunk_ao.prompt import Prompt if isinstance(prompt, Prompt): self.prompt_id = prompt.id @@ -922,7 +922,7 @@ def set_prompt( experiment.set_prompt(prompt_id="prompt-123") # Set prompt using Prompt object - from galileo.prompt import Prompt # noqa: PLC0415 + from splunk_ao.prompt import Prompt # noqa: PLC0415 prompt = Prompt.get(name="my-prompt") experiment.set_prompt(prompt=prompt) @@ -938,7 +938,7 @@ def set_prompt( # Handle prompt parameter if prompt is not None: # Local import to avoid circular dependency - from galileo.prompt import Prompt + from splunk_ao.prompt import Prompt if isinstance(prompt, Prompt): self.prompt_id = prompt.id @@ -1455,7 +1455,7 @@ def _get_columns(self, api_func: Any, error_msg: str) -> LogRecordsAvailableColu def project(self) -> Project | None: """Get the project this experiment belongs to.""" # Local import to avoid circular dependency - from galileo.project import Project + from splunk_ao.project import Project return Project.get(id=self.project_id) @@ -1465,7 +1465,7 @@ def dataset(self) -> Dataset | None: if self.dataset_id is None and self.dataset_name is None: return None # Local import to avoid circular dependency - from galileo.dataset import Dataset + from splunk_ao.dataset import Dataset if self.dataset_id: return Dataset.get(id=self.dataset_id) @@ -1483,7 +1483,7 @@ def prompt(self) -> Prompt | None: if self.prompt_id is None and self.prompt_name is None: return None # Local import to avoid circular dependency - from galileo.prompt import Prompt + from splunk_ao.prompt import Prompt if self.prompt_id: return Prompt.get(id=self.prompt_id) @@ -1782,7 +1782,7 @@ def model(self) -> Model | None: if self.model_alias: # Local import to avoid circular dependency - from galileo.model import Model + from splunk_ao.model import Model # Create a basic Model representation from the alias # Note: provider_name is unknown since we don't have integration context @@ -1931,7 +1931,7 @@ def experiment_columns(self) -> ColumnCollection: """ Get available metric columns for this experiment. - Returns a :class:`~galileo.shared.column.ColumnCollection` of all columns available + Returns a :class:`~splunk_ao.shared.column.ColumnCollection` of all columns available in the experiment comparison table. Scorer-backed metric columns carry UUID-based IDs of the form ``"metrics/{scorer-uuid}"``, which map directly to the keys returned by :attr:`metric_aggregates`. @@ -1958,7 +1958,7 @@ def experiment_columns(self) -> ColumnCollection: Returns ------- - ColumnCollection: Mapping of column ID to :class:`~galileo.shared.column.Column`, + ColumnCollection: Mapping of column ID to :class:`~splunk_ao.shared.column.Column`, accessible by full column ID (e.g. ``columns["metrics/{uuid}"]``). Raises @@ -1996,7 +1996,7 @@ def get_metric_aggregate(self, metric: SplunkAOMetrics | str) -> MetricAggregate Looks up a metric by any of the following identifiers, tried in order: - 1. :class:`~galileo.schema.metrics.SplunkAOMetrics` enum value — its + 1. :class:`~splunk_ao.schema.metrics.SplunkAOMetrics` enum value — its ``value`` IS the human-readable label (e.g. ``SplunkAOMetrics.correctness`` → ``"Correctness"``). 2. Scorer UUID string — direct lookup in :attr:`metric_aggregates`, @@ -2026,7 +2026,7 @@ def get_metric_aggregate(self, metric: SplunkAOMetrics | str) -> MetricAggregate -------- Poll until a specific metric is computed, then assert:: - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.schema.metrics import SplunkAOMetrics while experiment.get_metric_aggregate(SplunkAOMetrics.correctness) is None: time.sleep(5) @@ -2061,8 +2061,8 @@ def get_metric_aggregate(self, metric: SplunkAOMetrics | str) -> MetricAggregate # Import at end to avoid circular import (dataset.py, prompt.py, project.py import Experiment) -from galileo.dataset import Dataset # noqa: E402 -from galileo.model import Model # noqa: E402 -from galileo.project import Project # noqa: E402 -from galileo.prompt import Prompt # noqa: E402 -from galileo.shared.column import Column, ColumnCollection # noqa: E402 +from splunk_ao.dataset import Dataset # noqa: E402 +from splunk_ao.model import Model # noqa: E402 +from splunk_ao.project import Project # noqa: E402 +from splunk_ao.prompt import Prompt # noqa: E402 +from splunk_ao.shared.column import Column, ColumnCollection # noqa: E402 diff --git a/src/galileo/experiment_tags.py b/src/splunk_ao/experiment_tags.py similarity index 98% rename from src/galileo/experiment_tags.py rename to src/splunk_ao/experiment_tags.py index a0777fcb..f0954a21 100644 --- a/src/galileo/experiment_tags.py +++ b/src/splunk_ao/experiment_tags.py @@ -2,7 +2,6 @@ import logging -from galileo.config import SplunkAOConfig from galileo.resources.api.experiment_tags import ( delete_experiment_tag_projects_project_id_experiments_experiment_id_tags_tag_id_delete, get_experiment_tags_projects_project_id_experiments_experiment_id_tags_get, @@ -11,7 +10,8 @@ from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.run_tag_create_request import RunTagCreateRequest from galileo.resources.models.run_tag_db import RunTagDB -from galileo.utils.exceptions import APIException +from splunk_ao.config import SplunkAOConfig +from splunk_ao.utils.exceptions import APIException _logger = logging.getLogger(__name__) diff --git a/src/galileo/experiments.py b/src/splunk_ao/experiments.py similarity index 96% rename from src/galileo/experiments.py rename to src/splunk_ao/experiments.py index 24441e21..46cd516f 100644 --- a/src/galileo/experiments.py +++ b/src/splunk_ao/experiments.py @@ -8,26 +8,26 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -from galileo.config import SplunkAOConfig -from galileo.datasets import Dataset, convert_dataset_row_to_record -from galileo.decorator import galileo_context, galileo_dataset_context, log -from galileo.experiment_tags import upsert_experiment_tag -from galileo.projects import Project, Projects -from galileo.prompts import PromptTemplate from galileo.resources.api.experiment import ( create_experiment_projects_project_id_experiments_post, list_experiments_projects_project_id_experiments_get, ) from galileo.resources.models import ExperimentResponse, HTTPValidationError, PromptRunSettings, ScorerConfig, TaskType -from galileo.schema.datasets import DatasetRecord -from galileo.schema.experiment_group import ExperimentGroupResponse -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig, Metric -from galileo.utils.datasets import create_rows_from_records, load_dataset -from galileo.utils.exceptions import _format_http_validation_error -from galileo.utils.headers_data import get_sdk_header -from galileo.utils.log_config import get_logger -from galileo.utils.metrics import create_metric_configs from galileo_core.constants.request_method import RequestMethod +from splunk_ao.config import SplunkAOConfig +from splunk_ao.datasets import Dataset, convert_dataset_row_to_record +from splunk_ao.decorator import galileo_context, galileo_dataset_context, log +from splunk_ao.experiment_tags import upsert_experiment_tag +from splunk_ao.projects import Project, Projects +from splunk_ao.prompts import PromptTemplate +from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.schema.experiment_group import ExperimentGroupResponse +from splunk_ao.schema.metrics import LocalMetricConfig, Metric, SplunkAOMetrics +from splunk_ao.utils.datasets import create_rows_from_records, load_dataset +from splunk_ao.utils.exceptions import _format_http_validation_error +from splunk_ao.utils.headers_data import get_sdk_header +from splunk_ao.utils.log_config import get_logger +from splunk_ao.utils.metrics import create_metric_configs _logger = get_logger(__name__) @@ -368,7 +368,7 @@ def run_experiment( otherwise the run lands in the project's system "Ungrouped" group. experiment_group_id Optional UUID of an existing experiment group. If the group does not exist in this - project, the SDK raises ``galileo.NotFoundError`` (HTTP 404, + project, the SDK raises ``splunk_ao.NotFoundError`` (HTTP 404, API error_code 3520) before the run is created. If both ``experiment_group_id`` and ``experiment_group`` are provided, the API uses the ID and silently ignores the name. @@ -381,7 +381,7 @@ def run_experiment( ------ ValueError If required parameters are missing or invalid. - galileo.NotFoundError + splunk_ao.NotFoundError If ``experiment_group_id`` is provided but the group does not exist in the project. """ if isinstance(prompt_settings, dict): @@ -520,7 +520,7 @@ def create_experiment( this name does not exist in the project, the API auto-creates it. experiment_group_id Optional UUID of an existing experiment group. If the group does not exist in this - project, the SDK raises ``galileo.NotFoundError`` (HTTP 404, + project, the SDK raises ``splunk_ao.NotFoundError`` (HTTP 404, API error_code 3520). If both ``experiment_group_id`` and ``experiment_group`` are provided, the API uses the ID and silently ignores the name. @@ -535,7 +535,7 @@ def create_experiment( ValueError If `experiment_name` is not provided or if the project cannot be resolved from `project_id` or `project`. - galileo.NotFoundError + splunk_ao.NotFoundError If ``experiment_group_id`` is provided but the group does not exist in the project. HTTPValidationError If there's a validation error in returning an ExperimentResponse. diff --git a/src/galileo/export.py b/src/splunk_ao/export.py similarity index 96% rename from src/galileo/export.py rename to src/splunk_ao/export.py index a278096e..dc0c9dc8 100644 --- a/src/galileo/export.py +++ b/src/splunk_ao/export.py @@ -5,13 +5,13 @@ from collections.abc import Iterator from typing import Any -from galileo.config import SplunkAOConfig -from galileo.log_streams import LogStreams from galileo.resources.api.trace.export_records_projects_project_id_export_records_post import ( stream_detailed as export_records_stream, ) from galileo.resources.models import LLMExportFormat, LogRecordsExportRequest, LogRecordsSortClause, RootType -from galileo.schema.filters import FilterType +from splunk_ao.config import SplunkAOConfig +from splunk_ao.log_streams import LogStreams +from splunk_ao.schema.filters import FilterType logger = logging.getLogger(__name__) diff --git a/src/splunk_ao/handlers/agent_control/__init__.py b/src/splunk_ao/handlers/agent_control/__init__.py new file mode 100644 index 00000000..c9554a60 --- /dev/null +++ b/src/splunk_ao/handlers/agent_control/__init__.py @@ -0,0 +1,8 @@ +"""Agent Control bridge for Galileo logger-backed control span ingestion. + +For Agent Control target resolution, use ``splunk_ao.agent_control``. +""" + +from splunk_ao.handlers.agent_control.bridge import SplunkAOAgentControlBridge, setup_agent_control_bridge + +__all__ = ["SplunkAOAgentControlBridge", "setup_agent_control_bridge"] diff --git a/src/galileo/handlers/agent_control/bridge.py b/src/splunk_ao/handlers/agent_control/bridge.py similarity index 98% rename from src/galileo/handlers/agent_control/bridge.py rename to src/splunk_ao/handlers/agent_control/bridge.py index fdd0fb8c..fe720eb5 100644 --- a/src/galileo/handlers/agent_control/bridge.py +++ b/src/splunk_ao/handlers/agent_control/bridge.py @@ -9,9 +9,9 @@ from types import ModuleType from typing import Any -from galileo.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult -from galileo.logger.logger import SplunkAOLogger -from galileo.utils.serialization import serialize_to_str +from splunk_ao.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.utils.serialization import serialize_to_str logger = logging.getLogger(__name__) diff --git a/src/galileo/handlers/base_async_handler.py b/src/splunk_ao/handlers/base_async_handler.py similarity index 95% rename from src/galileo/handlers/base_async_handler.py rename to src/splunk_ao/handlers/base_async_handler.py index d0c44958..ea55e89d 100644 --- a/src/galileo/handlers/base_async_handler.py +++ b/src/splunk_ao/handlers/base_async_handler.py @@ -3,9 +3,9 @@ from typing import Any from uuid import UUID -from galileo.handlers.base_handler import SplunkAOBaseHandler -from galileo.schema.handlers import NODE_TYPE, Node -from galileo.utils.serialization import serialize_to_str +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.schema.handlers import NODE_TYPE, Node +from splunk_ao.utils.serialization import serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/galileo/handlers/base_handler.py b/src/splunk_ao/handlers/base_handler.py similarity index 97% rename from src/galileo/handlers/base_handler.py rename to src/splunk_ao/handlers/base_handler.py index 0822cea8..a65baef1 100644 --- a/src/galileo/handlers/base_handler.py +++ b/src/splunk_ao/handlers/base_handler.py @@ -5,11 +5,11 @@ from typing import Any from uuid import UUID -from galileo import galileo_context -from galileo.logger import SplunkAOLogger -from galileo.schema.handlers import INTEGRATION, NODE_TYPE, Node -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.serialization import convert_to_string_dict, serialize_to_str +from splunk_ao import galileo_context +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.handlers import INTEGRATION, NODE_TYPE, Node +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.serialization import convert_to_string_dict, serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/galileo/handlers/crewai/__init__.py b/src/splunk_ao/handlers/crewai/__init__.py similarity index 100% rename from src/galileo/handlers/crewai/__init__.py rename to src/splunk_ao/handlers/crewai/__init__.py diff --git a/src/galileo/handlers/crewai/handler.py b/src/splunk_ao/handlers/crewai/handler.py similarity index 99% rename from src/galileo/handlers/crewai/handler.py rename to src/splunk_ao/handlers/crewai/handler.py index b4a51263..11ae609b 100644 --- a/src/galileo/handlers/crewai/handler.py +++ b/src/splunk_ao/handlers/crewai/handler.py @@ -7,10 +7,10 @@ from packaging.version import Version -from galileo.handlers.base_handler import SplunkAOBaseHandler -from galileo.logger import SplunkAOLogger -from galileo.schema.handlers import NodeType -from galileo.utils.serialization import serialize_to_str +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.handlers import NodeType +from splunk_ao.utils.serialization import serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/splunk_ao/handlers/langchain/__init__.py b/src/splunk_ao/handlers/langchain/__init__.py new file mode 100644 index 00000000..8771654a --- /dev/null +++ b/src/splunk_ao/handlers/langchain/__init__.py @@ -0,0 +1,4 @@ +from splunk_ao.handlers.langchain.async_handler import SplunkAOAsyncCallback +from splunk_ao.handlers.langchain.handler import SplunkAOCallback + +__all__ = ("SplunkAOAsyncCallback", "SplunkAOCallback") diff --git a/src/galileo/handlers/langchain/async_handler.py b/src/splunk_ao/handlers/langchain/async_handler.py similarity index 96% rename from src/galileo/handlers/langchain/async_handler.py rename to src/splunk_ao/handlers/langchain/async_handler.py index b8d4fd3b..78706f09 100644 --- a/src/galileo/handlers/langchain/async_handler.py +++ b/src/splunk_ao/handlers/langchain/async_handler.py @@ -5,14 +5,14 @@ from typing import Any from uuid import UUID -from galileo.handlers.base_async_handler import SplunkAOAsyncBaseHandler -from galileo.handlers.langchain.handler import SplunkAOCallback -from galileo.handlers.langchain.utils import get_agent_name, is_agent_node, parse_llm_result, update_root_to_agent -from galileo.logger import SplunkAOLogger -from galileo.schema.handlers import NODE_TYPE -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.serialization import EventSerializer, serialize_to_str -from galileo.utils.uuid_utils import convert_uuid_if_uuid7 +from splunk_ao.handlers.base_async_handler import SplunkAOAsyncBaseHandler +from splunk_ao.handlers.langchain.handler import SplunkAOCallback +from splunk_ao.handlers.langchain.utils import get_agent_name, is_agent_node, parse_llm_result, update_root_to_agent +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.handlers import NODE_TYPE +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.serialization import EventSerializer, serialize_to_str +from splunk_ao.utils.uuid_utils import convert_uuid_if_uuid7 _logger = logging.getLogger(__name__) diff --git a/src/galileo/handlers/langchain/handler.py b/src/splunk_ao/handlers/langchain/handler.py similarity index 97% rename from src/galileo/handlers/langchain/handler.py rename to src/splunk_ao/handlers/langchain/handler.py index 37db3e4e..2477c56d 100644 --- a/src/galileo/handlers/langchain/handler.py +++ b/src/splunk_ao/handlers/langchain/handler.py @@ -5,13 +5,13 @@ from typing import Any from uuid import UUID -from galileo.handlers.base_handler import SplunkAOBaseHandler -from galileo.handlers.langchain.utils import get_agent_name, is_agent_node, parse_llm_result, update_root_to_agent -from galileo.logger import SplunkAOLogger -from galileo.schema.handlers import LANGCHAIN_NODE_TYPE, NODE_TYPE -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.serialization import EventSerializer, serialize_to_str -from galileo.utils.uuid_utils import convert_uuid_if_uuid7 +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.handlers.langchain.utils import get_agent_name, is_agent_node, parse_llm_result, update_root_to_agent +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.handlers import LANGCHAIN_NODE_TYPE, NODE_TYPE +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.serialization import EventSerializer, serialize_to_str +from splunk_ao.utils.uuid_utils import convert_uuid_if_uuid7 _logger = logging.getLogger(__name__) diff --git a/src/galileo/handlers/langchain/middleware.py b/src/splunk_ao/handlers/langchain/middleware.py similarity index 96% rename from src/galileo/handlers/langchain/middleware.py rename to src/splunk_ao/handlers/langchain/middleware.py index 77f9af5b..7ba23a2d 100644 --- a/src/galileo/handlers/langchain/middleware.py +++ b/src/splunk_ao/handlers/langchain/middleware.py @@ -8,13 +8,13 @@ from langchain_core.messages import AnyMessage from pydantic import BaseModel -from galileo.handlers.base_async_handler import SplunkAOAsyncBaseHandler -from galileo.handlers.base_handler import SplunkAOBaseHandler -from galileo.handlers.langchain.handler import SplunkAOCallback -from galileo.logger import SplunkAOLogger -from galileo.schema.trace import TracesIngestRequest -from galileo.utils.serialization import EventSerializer, serialize_to_str from galileo_core.schemas.logging.llm import Message, MessageRole +from splunk_ao.handlers.base_async_handler import SplunkAOAsyncBaseHandler +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.handlers.langchain.handler import SplunkAOCallback +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.trace import TracesIngestRequest +from splunk_ao.utils.serialization import EventSerializer, serialize_to_str try: from langchain_core.messages import AIMessage, BaseMessage diff --git a/src/galileo/handlers/langchain/tool.py b/src/splunk_ao/handlers/langchain/tool.py similarity index 97% rename from src/galileo/handlers/langchain/tool.py rename to src/splunk_ao/handlers/langchain/tool.py index 366494d9..3ac89de5 100644 --- a/src/galileo/handlers/langchain/tool.py +++ b/src/splunk_ao/handlers/langchain/tool.py @@ -4,13 +4,13 @@ from langchain_core.tools import BaseTool from pydantic import UUID4, BaseModel, ConfigDict, Field -from galileo.constants.protect import TIMEOUT_SECS -from galileo.protect import ainvoke_protect, invoke_protect -from galileo.utils.log_config import get_logger from galileo_core.schemas.protect.execution_status import ExecutionStatus from galileo_core.schemas.protect.payload import Payload as CorePayload from galileo_core.schemas.protect.response import Response from galileo_core.schemas.protect.ruleset import Ruleset +from splunk_ao.constants.protect import TIMEOUT_SECS +from splunk_ao.protect import ainvoke_protect, invoke_protect +from splunk_ao.utils.log_config import get_logger logger = get_logger(__name__) diff --git a/src/galileo/handlers/langchain/utils.py b/src/splunk_ao/handlers/langchain/utils.py similarity index 95% rename from src/galileo/handlers/langchain/utils.py rename to src/splunk_ao/handlers/langchain/utils.py index 810d76e8..e79c9bbf 100644 --- a/src/galileo/handlers/langchain/utils.py +++ b/src/splunk_ao/handlers/langchain/utils.py @@ -6,9 +6,9 @@ from typing import Any from uuid import UUID -from galileo.schema.handlers import Node -from galileo.utils.serialization import EventSerializer -from galileo.utils.uuid_utils import convert_uuid_if_uuid7 +from splunk_ao.schema.handlers import Node +from splunk_ao.utils.serialization import EventSerializer +from splunk_ao.utils.uuid_utils import convert_uuid_if_uuid7 _logger = logging.getLogger(__name__) diff --git a/src/splunk_ao/handlers/openai_agents/__init__.py b/src/splunk_ao/handlers/openai_agents/__init__.py new file mode 100644 index 00000000..d2e36e13 --- /dev/null +++ b/src/splunk_ao/handlers/openai_agents/__init__.py @@ -0,0 +1,3 @@ +from splunk_ao.handlers.openai_agents.handler import SplunkAOTracingProcessor + +__all__ = ["SplunkAOTracingProcessor"] diff --git a/src/galileo/handlers/openai_agents/handler.py b/src/splunk_ao/handlers/openai_agents/handler.py similarity index 98% rename from src/galileo/handlers/openai_agents/handler.py rename to src/splunk_ao/handlers/openai_agents/handler.py index 403c0654..5e1d333b 100644 --- a/src/galileo/handlers/openai_agents/handler.py +++ b/src/splunk_ao/handlers/openai_agents/handler.py @@ -6,10 +6,12 @@ from agents import Span, Trace, TracingProcessor from agents.tracing import ResponseSpanData, get_current_span, get_trace_provider -from galileo import SplunkAOLogger, galileo_context -from galileo.schema.handlers import Node -from galileo.utils import _get_timestamp -from galileo.utils.openai_agents import ( +from galileo_core.schemas.logging.span import LlmMetrics, LlmSpan +from galileo_core.schemas.logging.span import Span as GalileoSpan +from splunk_ao import SplunkAOLogger, galileo_context +from splunk_ao.schema.handlers import Node +from splunk_ao.utils import _get_timestamp +from splunk_ao.utils.openai_agents import ( SplunkAOCustomSpan, _extract_llm_data, _extract_tool_data, @@ -17,9 +19,7 @@ _map_span_name, _map_span_type, ) -from galileo.utils.serialization import convert_time_delta_to_ns, convert_to_string_dict, serialize_to_str -from galileo_core.schemas.logging.span import LlmMetrics, LlmSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from splunk_ao.utils.serialization import convert_time_delta_to_ns, convert_to_string_dict, serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/galileo/integration.py b/src/splunk_ao/integration.py similarity index 98% rename from src/galileo/integration.py rename to src/splunk_ao/integration.py index e6a62a25..c2f1204b 100644 --- a/src/galileo/integration.py +++ b/src/splunk_ao/integration.py @@ -4,7 +4,6 @@ from datetime import datetime from typing import TYPE_CHECKING, Any, cast -from galileo.config import SplunkAOConfig from galileo.resources.api.integrations import ( list_available_integrations_integrations_available_get, list_integrations_integrations_get, @@ -12,13 +11,14 @@ from galileo.resources.models.integration_db import IntegrationDB from galileo.resources.models.integration_name import IntegrationName from galileo.resources.types import Unset -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import APIError, ValidationError -from galileo.shared.utils import classproperty -from galileo.utils.exceptions import APIException +from splunk_ao.config import SplunkAOConfig +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import APIError, ValidationError +from splunk_ao.shared.utils import classproperty +from splunk_ao.utils.exceptions import APIException if TYPE_CHECKING: - from galileo.provider import ( + from splunk_ao.provider import ( AnthropicProvider, AzureProvider, BedrockProvider, @@ -637,7 +637,7 @@ def create_anthropic(cls, *, token: str) -> AnthropicProvider: # Import Provider classes at end to avoid circular imports -from galileo.provider import ( # noqa: E402 +from splunk_ao.provider import ( # noqa: E402 AnthropicProvider, AzureProvider, BedrockProvider, diff --git a/src/galileo/job_progress.py b/src/splunk_ao/job_progress.py similarity index 97% rename from src/galileo/job_progress.py rename to src/splunk_ao/job_progress.py index 912fd77b..c2f0ccb3 100644 --- a/src/galileo/job_progress.py +++ b/src/splunk_ao/job_progress.py @@ -5,15 +5,15 @@ from pydantic import UUID4 from tqdm.auto import tqdm -from galileo.config import SplunkAOConfig from galileo.resources.api.jobs import ( get_job_jobs_job_id_get, get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get, ) from galileo.resources.models import HTTPValidationError, JobDB -from galileo.utils.log_config import get_logger from galileo_core.constants.job import JobName, JobStatus from galileo_core.constants.scorers import Scorers +from splunk_ao.config import SplunkAOConfig +from splunk_ao.utils.log_config import get_logger _logger = get_logger(__name__) diff --git a/src/galileo/jobs.py b/src/splunk_ao/jobs.py similarity index 93% rename from src/galileo/jobs.py rename to src/splunk_ao/jobs.py index 9bdbf2f5..7ebeed4e 100644 --- a/src/galileo/jobs.py +++ b/src/splunk_ao/jobs.py @@ -1,6 +1,5 @@ import logging -from galileo.config import SplunkAOConfig from galileo.resources.api.jobs import create_job_jobs_post from galileo.resources.models import ( CreateJobRequest, @@ -10,7 +9,8 @@ ScorerConfig, TaskType, ) -from galileo.utils.exceptions import _format_http_validation_error +from splunk_ao.config import SplunkAOConfig +from splunk_ao.utils.exceptions import _format_http_validation_error _logger = logging.getLogger(__name__) diff --git a/src/galileo/log_stream.py b/src/splunk_ao/log_stream.py similarity index 97% rename from src/galileo/log_stream.py rename to src/splunk_ao/log_stream.py index 7a101089..cdaef55e 100644 --- a/src/galileo/log_stream.py +++ b/src/splunk_ao/log_stream.py @@ -6,10 +6,6 @@ from datetime import datetime from typing import TYPE_CHECKING, Any -from galileo.config import SplunkAOConfig -from galileo.decorator import galileo_context -from galileo.export import ExportClient -from galileo.log_streams import LogStreams from galileo.resources.api.trace import ( sessions_available_columns_projects_project_id_sessions_available_columns_post, spans_available_columns_projects_project_id_spans_available_columns_post, @@ -20,16 +16,20 @@ from galileo.resources.models.log_records_available_columns_request import LogRecordsAvailableColumnsRequest from galileo.resources.models.log_records_available_columns_response import LogRecordsAvailableColumnsResponse from galileo.resources.types import Unset -from galileo.schema.filters import FilterType -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig, Metric -from galileo.search import RecordType, Search -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import ValidationError -from galileo.shared.project_resolver import _resolve_project -from galileo.shared.query_result import QueryResult +from splunk_ao.config import SplunkAOConfig +from splunk_ao.decorator import galileo_context +from splunk_ao.export import ExportClient +from splunk_ao.log_streams import LogStreams +from splunk_ao.schema.filters import FilterType +from splunk_ao.schema.metrics import LocalMetricConfig, Metric, SplunkAOMetrics +from splunk_ao.search import RecordType, Search +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import ValidationError +from splunk_ao.shared.project_resolver import _resolve_project +from splunk_ao.shared.query_result import QueryResult if TYPE_CHECKING: - from galileo.shared.column import ColumnCollection + from splunk_ao.shared.column import ColumnCollection logger = logging.getLogger(__name__) @@ -69,13 +69,13 @@ class LogStream(StateManagementMixin): log_stream = LogStream.get(name="Production Logs", project_name="My AI Project") # LogStreams can also be created through Project instances - from galileo.project import Project + from splunk_ao.project import Project project = Project.get(name="My AI Project") log_stream = project.create_log_stream(name="Production Logs") # Enable metrics on the log stream - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.schema.metrics import SplunkAOMetrics local_metrics = log_stream.enable_metrics([ SplunkAOMetrics.correctness, SplunkAOMetrics.completeness, @@ -465,7 +465,7 @@ def set_metrics( Examples -------- - from galileo import Metric, LogStream + from splunk_ao import Metric, LogStream log_stream = LogStream.get(name="Production Logs", project_name="My Project") @@ -523,7 +523,7 @@ def query( Examples -------- - from galileo.search import RecordType + from splunk_ao.search import RecordType log_stream = LogStream.get(name="Production Logs", project_name="My AI Project") @@ -777,7 +777,7 @@ def export_records( Examples -------- - from galileo.search import RecordType + from splunk_ao.search import RecordType log_stream = LogStream.get(name="Production Logs", project_name="My AI Project") @@ -964,8 +964,8 @@ def trace_columns(self) -> ColumnCollection: # Import at end to avoid circular import (project.py imports LogStream) -from galileo.project import Project # noqa: E402 from galileo.resources.api.run_scorer_settings import ( # noqa: E402 get_settings_projects_project_id_runs_run_id_scorer_settings_get, ) -from galileo.shared.column import Column, ColumnCollection # noqa: E402 +from splunk_ao.project import Project # noqa: E402 +from splunk_ao.shared.column import Column, ColumnCollection # noqa: E402 diff --git a/src/galileo/log_streams.py b/src/splunk_ao/log_streams.py similarity index 95% rename from src/galileo/log_streams.py rename to src/splunk_ao/log_streams.py index cc9a436f..a98ce6fa 100644 --- a/src/galileo/log_streams.py +++ b/src/splunk_ao/log_streams.py @@ -1,8 +1,6 @@ import builtins from typing import overload -from galileo.config import SplunkAOConfig -from galileo.projects import Projects from galileo.resources.api.log_stream import ( create_log_stream_projects_project_id_log_streams_post, get_log_stream_projects_project_id_log_streams_log_stream_id_get, @@ -12,10 +10,12 @@ from galileo.resources.models.log_stream_create_request import LogStreamCreateRequest from galileo.resources.models.log_stream_response import LogStreamResponse from galileo.resources.types import Unset -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig, Metric -from galileo.utils.env_helpers import _get_log_stream_from_env, _get_project_from_env -from galileo.utils.log_config import get_logger -from galileo.utils.metrics import create_metric_configs +from splunk_ao.config import SplunkAOConfig +from splunk_ao.projects import Projects +from splunk_ao.schema.metrics import LocalMetricConfig, Metric, SplunkAOMetrics +from splunk_ao.utils.env_helpers import _get_log_stream_from_env, _get_project_from_env +from splunk_ao.utils.log_config import get_logger +from splunk_ao.utils.metrics import create_metric_configs logger = get_logger(__name__) @@ -48,7 +48,7 @@ class LogStream(LogStreamResponse): -------- ```python # Create a new log stream in a project - from galileo.log_streams import create_log_stream + from splunk_ao.log_streams import create_log_stream # Create by project ID log_stream = create_log_stream(name="Production Logs", project_id="project-123") @@ -57,18 +57,18 @@ class LogStream(LogStreamResponse): log_stream = create_log_stream(name="Production Logs", project_name="My AI Project") # Get a log stream by name - from galileo.log_streams import get_log_stream + from splunk_ao.log_streams import get_log_stream log_stream = get_log_stream(name="Production Logs", project_name="My AI Project") # List all log streams in a project - from galileo.log_streams import list_log_streams + from splunk_ao.log_streams import list_log_streams log_streams = list_log_streams(project_name="My AI Project") for stream in log_streams: logger.info(f"Log Stream: {stream.name} (ID: {stream.id})") # Use a log stream with the context manager - from galileo.openai import openai - from galileo import galileo_context + from splunk_ao.openai import openai + from splunk_ao import galileo_context with galileo_context(project="My AI Project", log_stream="Production Logs"): response = openai.chat.completions.create( @@ -77,8 +77,8 @@ class LogStream(LogStreamResponse): ) # Enable metrics on a log stream - RECOMMENDED APPROACH - from galileo.log_streams import enable_metrics - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.log_streams import enable_metrics + from splunk_ao.schema.metrics import SplunkAOMetrics # Set environment variables first # export SPLUNK_AO_LOG_STREAM="Production Logs" @@ -168,8 +168,8 @@ def enable_metrics( Basic usage with built-in metrics: ```python - from galileo.log_streams import LogStreams - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.log_streams import LogStreams + from splunk_ao.schema.metrics import SplunkAOMetrics # Get a log stream first log_streams = LogStreams() @@ -190,7 +190,7 @@ def enable_metrics( Advanced usage with custom metrics: ```python - from galileo.schema.metrics import Metric, LocalMetricConfig + from splunk_ao.schema.metrics import Metric, LocalMetricConfig def custom_scorer(trace_or_span): return 0.75 # Your scoring logic @@ -519,8 +519,8 @@ def enable_metrics( -------- ```python # Enable built-in metrics with explicit parameters - from galileo.log_streams import LogStreams - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.log_streams import LogStreams + from splunk_ao.schema.metrics import SplunkAOMetrics log_streams = LogStreams() scorer_configs, local_metrics = log_streams.enable_metrics( @@ -541,7 +541,7 @@ def enable_metrics( ) # Enable custom metrics with mixed parameters - from galileo.schema.metrics import Metric, LocalMetricConfig + from splunk_ao.schema.metrics import Metric, LocalMetricConfig def custom_scorer(trace_or_span): return 0.85 # Custom scoring logic @@ -739,8 +739,8 @@ def enable_metrics( -------- ```python # Enable built-in metrics with explicit parameters - from galileo.log_streams import enable_metrics - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.log_streams import enable_metrics + from splunk_ao.schema.metrics import SplunkAOMetrics local_metrics = enable_metrics( log_stream_name="Production Logs", @@ -758,7 +758,7 @@ def enable_metrics( local_metrics = enable_metrics(metrics=["correctness", "completeness"]) # Enable custom and local metrics with environment variable fallbacks - from galileo.schema.metrics import Metric, LocalMetricConfig + from splunk_ao.schema.metrics import Metric, LocalMetricConfig from galileo_core.schemas.logging.step import StepType def response_length_scorer(trace_or_span): diff --git a/src/galileo/logger/__init__.py b/src/splunk_ao/logger/__init__.py similarity index 75% rename from src/galileo/logger/__init__.py rename to src/splunk_ao/logger/__init__.py index 98dc8650..619e2a01 100644 --- a/src/galileo/logger/__init__.py +++ b/src/splunk_ao/logger/__init__.py @@ -5,12 +5,12 @@ __all__ = ["SplunkAOLogger"] if TYPE_CHECKING: - from galileo.logger.logger import SplunkAOLogger + from splunk_ao.logger.logger import SplunkAOLogger def __getattr__(name: str) -> Any: if name == "SplunkAOLogger": - from galileo.logger.logger import SplunkAOLogger + from splunk_ao.logger.logger import SplunkAOLogger return SplunkAOLogger raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/galileo/logger/control.py b/src/splunk_ao/logger/control.py similarity index 100% rename from src/galileo/logger/control.py rename to src/splunk_ao/logger/control.py diff --git a/src/galileo/logger/logger.py b/src/splunk_ao/logger/logger.py similarity index 98% rename from src/galileo/logger/logger.py rename to src/splunk_ao/logger/logger.py index 2d7c9836..1d08fe13 100644 --- a/src/galileo/logger/logger.py +++ b/src/splunk_ao/logger/logger.py @@ -13,26 +13,44 @@ from typing import TYPE_CHECKING, Any, Union if TYPE_CHECKING: - from galileo.handlers.agent_control import SplunkAOAgentControlBridge + from splunk_ao.handlers.agent_control import SplunkAOAgentControlBridge import backoff import httpx -from galileo.config import SplunkAOConfig -from galileo.constants import LoggerModeType -from galileo.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER -from galileo.exceptions import SplunkAOLoggerException -from galileo.log_streams import LogStreams -from galileo.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult -from galileo.logger.task_handler import ThreadPoolTaskHandler -from galileo.projects import Projects -from galileo.schema.content_blocks import ( +from galileo_core.helpers.execution import async_run +from galileo_core.schemas.logging.agent import AgentType +from galileo_core.schemas.logging.llm import Event +from galileo_core.schemas.logging.span import ( + LlmMetrics, + LlmSpan, + LlmSpanAllowedInputType, + LlmSpanAllowedOutputType, + RetrieverSpan, + Span, + StepWithChildSpans, + ToolSpan, +) +from galileo_core.schemas.logging.step import BaseStep, Metrics, StepType +from galileo_core.schemas.logging.trace import Trace +from galileo_core.schemas.protect.payload import Payload +from galileo_core.schemas.protect.response import Response +from galileo_core.schemas.shared.traces_logger import TracesLogger +from splunk_ao.config import SplunkAOConfig +from splunk_ao.constants import LoggerModeType +from splunk_ao.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER +from splunk_ao.exceptions import SplunkAOLoggerException +from splunk_ao.log_streams import LogStreams +from splunk_ao.logger.control import ControlAppliesTo, ControlCheckStage, ControlResult +from splunk_ao.logger.task_handler import ThreadPoolTaskHandler +from splunk_ao.projects import Projects +from splunk_ao.schema.content_blocks import ( DataContentBlock, TextContentBlock, is_content_block_list, normalize_content_block_list, ) -from galileo.schema.logged import ( +from splunk_ao.schema.logged import ( IngestOutputType, LoggedAgentSpan, LoggedControlSpan, @@ -41,8 +59,8 @@ LoggedWorkflowSpan, TextOrContentBlocks, ) -from galileo.schema.metrics import LocalMetricConfig -from galileo.schema.trace import ( +from splunk_ao.schema.metrics import LocalMetricConfig +from splunk_ao.schema.trace import ( LogRecordsSearchFilter, LogRecordsSearchFilterOperator, LogRecordsSearchFilterType, @@ -54,42 +72,24 @@ TracesIngestRequest, TraceUpdateRequest, ) -from galileo.traces import IngestTraces, Traces -from galileo.utils.decorators import ( +from splunk_ao.traces import IngestTraces, Traces +from splunk_ao.utils.decorators import ( async_warn_catch_exception, nop_async, nop_sync, retry_on_transient_http_error, warn_catch_exception, ) -from galileo.utils.env_helpers import ( +from splunk_ao.utils.env_helpers import ( _get_log_stream_id_from_env, _get_log_stream_or_default, _get_mode_or_default, _get_project_id_from_env, _get_project_or_default, ) -from galileo.utils.metrics import populate_local_metrics -from galileo.utils.retrievers import convert_to_documents -from galileo.utils.serialization import serialize_to_str -from galileo_core.helpers.execution import async_run -from galileo_core.schemas.logging.agent import AgentType -from galileo_core.schemas.logging.llm import Event -from galileo_core.schemas.logging.span import ( - LlmMetrics, - LlmSpan, - LlmSpanAllowedInputType, - LlmSpanAllowedOutputType, - RetrieverSpan, - Span, - StepWithChildSpans, - ToolSpan, -) -from galileo_core.schemas.logging.step import BaseStep, Metrics, StepType -from galileo_core.schemas.logging.trace import Trace -from galileo_core.schemas.protect.payload import Payload -from galileo_core.schemas.protect.response import Response -from galileo_core.schemas.shared.traces_logger import TracesLogger +from splunk_ao.utils.metrics import populate_local_metrics +from splunk_ao.utils.retrievers import convert_to_documents +from splunk_ao.utils.serialization import serialize_to_str # Type alias for metadata values that can be auto-converted to strings MetadataValue = str | bool | int | float | None @@ -110,7 +110,7 @@ # Cached result of the ingest service healthz probe. Key "result" is absent until first check. _ingest_service_cache: dict[str, bool] = {} -_logger = logging.getLogger("galileo.logger") +_logger = logging.getLogger("splunk_ao.logger") class SplunkAOLogger(TracesLogger): @@ -187,7 +187,7 @@ class SplunkAOLogger(TracesLogger): mode: LoggerModeType | None = None _session_external_id: str | None = None - _logger = logging.getLogger("galileo.logger") + _logger = logging.getLogger("splunk_ao.logger") _traces_client: Union["Traces", "IngestTraces"] | None = None _task_handler: ThreadPoolTaskHandler _trace_completion_submitted: bool @@ -319,7 +319,9 @@ def __init__( # When using ingestion_hook, log_stream is optional (hook handles ingestion) if not self._ingestion_hook: if self.log_stream_name is None and self.log_stream_id is None: - raise SplunkAOLoggerException("log_stream or log_stream_id is required to initialize SplunkAOLogger.") + raise SplunkAOLoggerException( + "log_stream or log_stream_id is required to initialize SplunkAOLogger." + ) if local_metrics: self.local_metrics = local_metrics @@ -912,7 +914,7 @@ def has_active_trace(self) -> bool: def enable_agent_control(self) -> "SplunkAOAgentControlBridge": """Register this logger as the active Agent Control bridge target.""" - from galileo.handlers.agent_control import SplunkAOAgentControlBridge + from splunk_ao.handlers.agent_control import SplunkAOAgentControlBridge bridge = getattr(self, "_agent_control_bridge", None) if bridge is None: diff --git a/src/galileo/logger/task_handler.py b/src/splunk_ao/logger/task_handler.py similarity index 100% rename from src/galileo/logger/task_handler.py rename to src/splunk_ao/logger/task_handler.py diff --git a/src/galileo/logger/utils.py b/src/splunk_ao/logger/utils.py similarity index 86% rename from src/galileo/logger/utils.py rename to src/splunk_ao/logger/utils.py index 104cb636..2d7fb015 100644 --- a/src/galileo/logger/utils.py +++ b/src/splunk_ao/logger/utils.py @@ -1,9 +1,9 @@ import logging -from galileo.utils.decorators import nop_sync -from galileo.utils.serialization import serialize_to_str from galileo_core.schemas.logging.span import StepWithChildSpans from galileo_core.schemas.logging.step import BaseStep +from splunk_ao.utils.decorators import nop_sync +from splunk_ao.utils.serialization import serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/galileo/metric.py b/src/splunk_ao/metric.py similarity index 98% rename from src/galileo/metric.py rename to src/splunk_ao/metric.py index 1e03e79c..bd3c4f69 100644 --- a/src/galileo/metric.py +++ b/src/splunk_ao/metric.py @@ -11,11 +11,8 @@ from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from galileo.model import Model + from splunk_ao.model import Model -from galileo.config import SplunkAOConfig -from galileo.configuration import Configuration -from galileo.metrics import Metrics from galileo.resources.api.data import ( create_code_scorer_version_scorers_scorer_id_version_code_post, create_scorers_post, @@ -35,15 +32,18 @@ ) from galileo.resources.models.invalid_result import InvalidResult from galileo.resources.types import UNSET, File, Unset -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig -from galileo.schema.metrics import Metric as LegacyMetric -from galileo.scorers import Scorers -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import APIError, ValidationError from galileo_core.schemas.logging.span import Span from galileo_core.schemas.logging.step import StepType from galileo_core.schemas.logging.trace import Trace from galileo_core.schemas.shared.metric import MetricValueType +from splunk_ao.config import SplunkAOConfig +from splunk_ao.configuration import Configuration +from splunk_ao.metrics import Metrics +from splunk_ao.schema.metrics import LocalMetricConfig, SplunkAOMetrics +from splunk_ao.schema.metrics import Metric as LegacyMetric +from splunk_ao.scorers import Scorers +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import APIError, ValidationError logger = logging.getLogger(__name__) @@ -60,7 +60,7 @@ class BuiltInMetrics: Examples -------- - from galileo.metric import Metric + from splunk_ao.metric import Metric # Access built-in metrics Metric.metrics.correctness @@ -115,7 +115,7 @@ class Metric(StateManagementMixin, ABC): Examples -------- # 1. Use built-in Galileo scorers - from galileo import Metric, SplunkAOMetric, LlmMetric, LocalMetric, LogStream + from splunk_ao import Metric, SplunkAOMetric, LlmMetric, LocalMetric, LogStream log_stream = LogStream.get(name="my-stream", project_name="my-project") log_stream.set_metrics([ @@ -593,7 +593,7 @@ def refresh(self) -> None: def to_legacy_metric(self) -> LegacyMetric: """ - Convert to legacy galileo.schema.metrics.Metric format. + Convert to legacy splunk_ao.schema.metrics.Metric format. This enables backward compatibility with existing code that uses the legacy Metric class. @@ -672,7 +672,7 @@ class LlmMetric(Metric): ).create() # Or use a Model object from Integration - from galileo.integration import Integration + from splunk_ao.integration import Integration gpt_model = Integration.openai.get_model(alias="gpt-4o-mini") metric = LlmMetric( name="response_quality", @@ -746,7 +746,7 @@ def __init__( # Handle model parameter - extract alias from Model object if needed if model is not None: # Local import to avoid circular dependency - from galileo.model import Model + from splunk_ao.model import Model final_model = model.alias if isinstance(model, Model) else model else: @@ -1171,7 +1171,7 @@ class SplunkAOMetric(Metric): Examples -------- # Access built-in scorers - from galileo import Metric, LogStream + from splunk_ao import Metric, LogStream log_stream = LogStream.get(name="my-stream", project_name="my-project") log_stream.set_metrics([ diff --git a/src/galileo/metrics.py b/src/splunk_ao/metrics.py similarity index 98% rename from src/galileo/metrics.py rename to src/splunk_ao/metrics.py index d46ea718..c65057d8 100644 --- a/src/galileo/metrics.py +++ b/src/splunk_ao/metrics.py @@ -1,7 +1,6 @@ import datetime import logging -from galileo.config import SplunkAOConfig from galileo.resources.api.data import ( create_llm_scorer_version_scorers_scorer_id_version_llm_post, create_scorers_post, @@ -19,9 +18,10 @@ from galileo.resources.models.create_scorer_request import CreateScorerRequest from galileo.resources.models.output_type_enum import OutputTypeEnum from galileo.resources.models.scorer_defaults import ScorerDefaults -from galileo.scorers import Scorers -from galileo.search import FilterType from galileo_core.schemas.logging.step import StepType +from splunk_ao.config import SplunkAOConfig +from splunk_ao.scorers import Scorers +from splunk_ao.search import FilterType _logger = logging.getLogger(__name__) diff --git a/src/galileo/middleware/__init__.py b/src/splunk_ao/middleware/__init__.py similarity index 56% rename from src/galileo/middleware/__init__.py rename to src/splunk_ao/middleware/__init__.py index a3f7e461..1af15f8d 100644 --- a/src/galileo/middleware/__init__.py +++ b/src/splunk_ao/middleware/__init__.py @@ -1,5 +1,5 @@ """Galileo middleware for web frameworks.""" -from galileo.middleware.tracing import TracingMiddleware, get_request_logger +from splunk_ao.middleware.tracing import TracingMiddleware, get_request_logger __all__ = ["TracingMiddleware", "get_request_logger"] diff --git a/src/galileo/middleware/tracing.py b/src/splunk_ao/middleware/tracing.py similarity index 95% rename from src/galileo/middleware/tracing.py rename to src/splunk_ao/middleware/tracing.py index d1c971da..75b24b5d 100644 --- a/src/galileo/middleware/tracing.py +++ b/src/splunk_ao/middleware/tracing.py @@ -12,7 +12,7 @@ Example usage with FastAPI: ```python from fastapi import FastAPI - from galileo.middleware import TracingMiddleware, get_request_logger + from splunk_ao.middleware import TracingMiddleware, get_request_logger app = FastAPI() app.add_middleware(TracingMiddleware) @@ -31,7 +31,7 @@ async def process_request(data: dict): ```python from starlette.applications import Starlette from starlette.routing import Route - from galileo.middleware import TracingMiddleware, get_request_logger + from splunk_ao.middleware import TracingMiddleware, get_request_logger async def homepage(request): logger = get_request_logger() @@ -49,9 +49,9 @@ async def homepage(request): import logging from typing import Any, NoReturn -from galileo.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER -from galileo.decorator import _parent_id_context, _trace_id_context -from galileo.logger import SplunkAOLogger +from splunk_ao.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER +from splunk_ao.decorator import _parent_id_context, _trace_id_context +from splunk_ao.logger import SplunkAOLogger _logger = logging.getLogger(__name__) diff --git a/src/galileo/model.py b/src/splunk_ao/model.py similarity index 100% rename from src/galileo/model.py rename to src/splunk_ao/model.py diff --git a/src/galileo/openai/__init__.py b/src/splunk_ao/openai/__init__.py similarity index 96% rename from src/galileo/openai/__init__.py rename to src/splunk_ao/openai/__init__.py index 126af00d..2d769aac 100644 --- a/src/galileo/openai/__init__.py +++ b/src/splunk_ao/openai/__init__.py @@ -11,7 +11,7 @@ -------- ```python # Import the wrapped OpenAI client instead of the original -from galileo.openai import openai +from splunk_ao.openai import openai # Use it exactly as you would use the regular OpenAI client response = openai.chat.completions.create( @@ -26,7 +26,7 @@ print(response.choices[0].message.content) # You can also use it with the galileo_context for more control -from galileo import galileo_context +from splunk_ao import galileo_context with galileo_context(project="my-project", log_stream="my-log-stream"): response = openai.chat.completions.create( @@ -46,9 +46,9 @@ import httpx from wrapt import wrap_function_wrapper # type: ignore[import-untyped] -from galileo.decorator import galileo_context -from galileo.logger import SplunkAOLogger -from galileo.openai.extractors import ( +from splunk_ao.decorator import galileo_context +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.openai.extractors import ( OpenAiArgsExtractor, convert_to_galileo_message, extract_data_from_default_response, @@ -59,10 +59,10 @@ process_function_call_outputs, process_output_items, ) -from galileo.openai.models import OpenAiModuleDefinition -from galileo.openai.response_generator import ResponseGeneratorSync -from galileo.utils import _get_timestamp -from galileo.utils.serialization import serialize_to_str +from splunk_ao.openai.models import OpenAiModuleDefinition +from splunk_ao.openai.response_generator import ResponseGeneratorSync +from splunk_ao.utils import _get_timestamp +from splunk_ao.utils.serialization import serialize_to_str try: import openai @@ -282,7 +282,7 @@ def _wrap( raise RuntimeError("Failed to process the OpenAI Request") from ex -class OpenAISplunkAO: +class OpenAIGalileo: """ This class is responsible for logging OpenAI API calls and logging them to Galileo. It wraps the OpenAI client methods to add logging functionality without changing @@ -332,5 +332,5 @@ def register_tracing(self) -> None: ) -modifier = OpenAISplunkAO() +modifier = OpenAIGalileo() modifier.register_tracing() diff --git a/src/galileo/openai/extractors.py b/src/splunk_ao/openai/extractors.py similarity index 99% rename from src/galileo/openai/extractors.py rename to src/splunk_ao/openai/extractors.py index 6fb01c79..d9e44407 100644 --- a/src/galileo/openai/extractors.py +++ b/src/splunk_ao/openai/extractors.py @@ -11,9 +11,9 @@ from packaging.version import Version from pydantic import BaseModel -from galileo.logger import SplunkAOLogger -from galileo.openai.models import OpenAiInputData, OpenAiModuleDefinition from galileo_core.schemas.logging.llm import Event, Message, MessageRole, ReasoningEvent, ToolCall, ToolCallFunction +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.openai.models import OpenAiInputData, OpenAiModuleDefinition try: import openai diff --git a/src/galileo/openai/models.py b/src/splunk_ao/openai/models.py similarity index 100% rename from src/galileo/openai/models.py rename to src/splunk_ao/openai/models.py diff --git a/src/galileo/openai/response_generator.py b/src/splunk_ao/openai/response_generator.py similarity index 97% rename from src/galileo/openai/response_generator.py rename to src/splunk_ao/openai/response_generator.py index 0b9d5cf2..fb95ecf9 100644 --- a/src/galileo/openai/response_generator.py +++ b/src/splunk_ao/openai/response_generator.py @@ -2,17 +2,17 @@ from datetime import datetime from typing import Any -from galileo import SplunkAOLogger -from galileo.openai.extractors import ( +from splunk_ao import SplunkAOLogger +from splunk_ao.openai.extractors import ( convert_to_galileo_message, extract_streamed_openai_response, has_pending_function_calls, process_function_call_outputs, process_output_items, ) -from galileo.openai.models import OpenAiInputData, OpenAiModuleDefinition -from galileo.utils import _get_timestamp -from galileo.utils.serialization import serialize_to_str +from splunk_ao.openai.models import OpenAiInputData, OpenAiModuleDefinition +from splunk_ao.utils import _get_timestamp +from splunk_ao.utils.serialization import serialize_to_str try: import openai diff --git a/src/galileo/otel.py b/src/splunk_ao/otel.py similarity index 89% rename from src/galileo/otel.py rename to src/splunk_ao/otel.py index b74ddcd1..1acc6677 100644 --- a/src/galileo/otel.py +++ b/src/splunk_ao/otel.py @@ -9,8 +9,10 @@ from requests import Session -from galileo.config import SplunkAOConfig -from galileo.decorator import ( +from galileo_core.schemas.logging.span import RetrieverSpan, ToolSpan, WorkflowSpan +from galileo_core.schemas.logging.span import Span as GalileoSpan +from splunk_ao.config import SplunkAOConfig +from splunk_ao.decorator import ( _dataset_input_context, _dataset_metadata_context, _dataset_output_context, @@ -19,10 +21,8 @@ _project_context, _session_id_context, ) -from galileo.utils.env_helpers import _get_log_stream_or_default, _get_project_or_default -from galileo.utils.retrievers import document_adapter -from galileo_core.schemas.logging.span import RetrieverSpan, ToolSpan, WorkflowSpan -from galileo_core.schemas.logging.span import Span as GalileoSpan +from splunk_ao.utils.env_helpers import _get_log_stream_or_default, _get_project_or_default +from splunk_ao.utils.retrievers import document_adapter logger = logging.getLogger(__name__) @@ -149,32 +149,32 @@ def export(self, spans: typing.Sequence[Any]) -> "Any": is_experiment = False for span in spans: # Read from span attributes (set during on_start when context was available) - project = span.attributes.get("galileo.project.name") - logstream = span.attributes.get("galileo.logstream.name") - session_id = span.attributes.get("galileo.session.id") - experiment_id = span.attributes.get("galileo.experiment.id") - dataset_input = span.attributes.get("galileo.dataset.input") - dataset_output = span.attributes.get("galileo.dataset.output") - dataset_metadata = span.attributes.get("galileo.dataset.metadata") + project = span.attributes.get("splunk_ao.project.name") + logstream = span.attributes.get("splunk_ao.logstream.name") + session_id = span.attributes.get("splunk_ao.session.id") + experiment_id = span.attributes.get("splunk_ao.experiment.id") + dataset_input = span.attributes.get("splunk_ao.dataset.input") + dataset_output = span.attributes.get("splunk_ao.dataset.output") + dataset_metadata = span.attributes.get("splunk_ao.dataset.metadata") # Build resource attributes dict, filtering out None values resource_attrs = {} if project: - resource_attrs["galileo.project.name"] = project + resource_attrs["splunk_ao.project.name"] = project # We can only have either logstream or experiment, if it's an experiment we want to prioritize it. if logstream and not experiment_id: - resource_attrs["galileo.logstream.name"] = logstream + resource_attrs["splunk_ao.logstream.name"] = logstream if session_id: - resource_attrs["galileo.session.id"] = session_id + resource_attrs["splunk_ao.session.id"] = session_id if experiment_id: - resource_attrs["galileo.experiment.id"] = experiment_id + resource_attrs["splunk_ao.experiment.id"] = experiment_id is_experiment = True if dataset_input: - resource_attrs["galileo.dataset.input"] = dataset_input + resource_attrs["splunk_ao.dataset.input"] = dataset_input if dataset_output: - resource_attrs["galileo.dataset.output"] = dataset_output + resource_attrs["splunk_ao.dataset.output"] = dataset_output if dataset_metadata: - resource_attrs["galileo.dataset.metadata"] = dataset_metadata + resource_attrs["splunk_ao.dataset.metadata"] = dataset_metadata if resource_attrs: # Merge new attributes into span's resource @@ -187,12 +187,12 @@ def export(self, spans: typing.Sequence[Any]) -> "Any": last_span = spans[-1] self._session.headers.update( { - "project": last_span.attributes.get("galileo.project.name"), - "logstream": last_span.attributes.get("galileo.logstream.name"), + "project": last_span.attributes.get("splunk_ao.project.name"), + "logstream": last_span.attributes.get("splunk_ao.logstream.name"), } ) if is_experiment: - self._session.headers.update({"experimentid": last_span.attributes.get("galileo.experiment.id")}) + self._session.headers.update({"experimentid": last_span.attributes.get("splunk_ao.experiment.id")}) self._session.headers.pop("logstream", None) # Remove logstream header if experiment is present return super().export(spans) @@ -265,14 +265,14 @@ def on_start(self, span: Span, parent_context: context.Context | None = None) -> session_id = _session_id_context.get(None) if project: - span.set_attribute("galileo.project.name", project) + span.set_attribute("splunk_ao.project.name", project) # We can only have either logstream or experiment, if it's an experiment we want to prioritize it. if log_stream and not experiment_id: - span.set_attribute("galileo.logstream.name", log_stream) + span.set_attribute("splunk_ao.logstream.name", log_stream) if experiment_id: - span.set_attribute("galileo.experiment.id", experiment_id) + span.set_attribute("splunk_ao.experiment.id", experiment_id) if session_id: - span.set_attribute("galileo.session.id", session_id) + span.set_attribute("splunk_ao.session.id", session_id) # Set dataset attributes for ground truth/reference output support _apply_dataset_attributes( @@ -351,11 +351,11 @@ def _apply_dataset_attributes( ) -> None: """Write dataset context attributes onto a span.""" if dataset_input is not None: - span.set_attribute("galileo.dataset.input", dataset_input) + span.set_attribute("splunk_ao.dataset.input", dataset_input) if dataset_output is not None: - span.set_attribute("galileo.dataset.output", dataset_output) + span.set_attribute("splunk_ao.dataset.output", dataset_output) if dataset_metadata is not None: - span.set_attribute("galileo.dataset.metadata", json.dumps(dataset_metadata)) + span.set_attribute("splunk_ao.dataset.metadata", json.dumps(dataset_metadata)) def _set_workflow_span_attributes(span: trace.Span, galileo_span: WorkflowSpan) -> None: diff --git a/src/galileo/project.py b/src/splunk_ao/project.py similarity index 97% rename from src/galileo/project.py rename to src/splunk_ao/project.py index 57a6ee21..1abb4b4f 100644 --- a/src/galileo/project.py +++ b/src/splunk_ao/project.py @@ -5,21 +5,21 @@ from datetime import datetime from typing import TYPE_CHECKING, Any -from galileo.collaborator import Collaborator, CollaboratorRole -from galileo.config import SplunkAOConfig -from galileo.projects import Projects from galileo.resources.api.projects import update_project_projects_project_id_put from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.project_update import ProjectUpdate from galileo.resources.types import Unset -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import APIError, ValidationError +from splunk_ao.collaborator import Collaborator, CollaboratorRole +from splunk_ao.config import SplunkAOConfig +from splunk_ao.projects import Projects +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import APIError, ValidationError if TYPE_CHECKING: - from galileo.dataset import Dataset - from galileo.experiment import Experiment - from galileo.log_stream import LogStream - from galileo.prompt import Prompt + from splunk_ao.dataset import Dataset + from splunk_ao.experiment import Experiment + from splunk_ao.log_stream import LogStream + from splunk_ao.prompt import Prompt logger = logging.getLogger(__name__) @@ -893,7 +893,7 @@ def save(self) -> Project: # Import at end to avoid circular import (log_stream.py imports Project) -from galileo.dataset import Dataset # noqa: E402 -from galileo.experiment import Experiment # noqa: E402 -from galileo.log_stream import LogStream # noqa: E402 -from galileo.prompt import Prompt # noqa: E402 +from splunk_ao.dataset import Dataset # noqa: E402 +from splunk_ao.experiment import Experiment # noqa: E402 +from splunk_ao.log_stream import LogStream # noqa: E402 +from splunk_ao.prompt import Prompt # noqa: E402 diff --git a/src/galileo/projects.py b/src/splunk_ao/projects.py similarity index 98% rename from src/galileo/projects.py rename to src/splunk_ao/projects.py index cb058409..b768f2a9 100644 --- a/src/galileo/projects.py +++ b/src/splunk_ao/projects.py @@ -3,7 +3,6 @@ import httpx -from galileo.config import SplunkAOConfig from galileo.resources.api.projects import ( create_project_projects_post, create_user_project_collaborators_projects_project_id_users_post, @@ -28,9 +27,10 @@ from galileo.resources.models.user_collaborator import UserCollaborator from galileo.resources.models.user_collaborator_create import UserCollaboratorCreate from galileo.resources.types import UNSET, Unset -from galileo.utils.env_helpers import _get_project_from_env, _get_project_id_from_env -from galileo.utils.exceptions import APIException -from galileo.utils.log_config import get_logger +from splunk_ao.config import SplunkAOConfig +from splunk_ao.utils.env_helpers import _get_project_from_env, _get_project_id_from_env +from splunk_ao.utils.exceptions import APIException +from splunk_ao.utils.log_config import get_logger _logger = get_logger(__name__) @@ -72,7 +72,7 @@ class Project: Examples -------- ```python - from galileo.projects import get_project, create_project, list_projects, delete_project + from splunk_ao.projects import get_project, create_project, list_projects, delete_project # Create a new project project = create_project(name="My AI Project") diff --git a/src/galileo/prompt.py b/src/splunk_ao/prompt.py similarity index 98% rename from src/galileo/prompt.py rename to src/splunk_ao/prompt.py index f9dd346e..86f34d36 100644 --- a/src/galileo/prompt.py +++ b/src/splunk_ao/prompt.py @@ -6,9 +6,6 @@ from datetime import datetime from typing import TYPE_CHECKING, Any -from galileo.config import SplunkAOConfig -from galileo.projects import Projects -from galileo.prompts import GlobalPromptTemplates from galileo.resources.api.prompts import ( create_global_prompt_template_version_templates_template_id_versions_post, query_template_versions_templates_template_id_versions_query_post, @@ -21,11 +18,14 @@ MessagesListItem, ) from galileo.resources.types import Unset -from galileo.schema.message import Message -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError -from galileo.utils.env_helpers import _get_project_from_env, _get_project_id_from_env from galileo_core.schemas.logging.llm import MessageRole +from splunk_ao.config import SplunkAOConfig +from splunk_ao.projects import Projects +from splunk_ao.prompts import GlobalPromptTemplates +from splunk_ao.schema.message import Message +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError +from splunk_ao.utils.env_helpers import _get_project_from_env, _get_project_id_from_env if TYPE_CHECKING: from galileo.resources.models import PromptRunSettings diff --git a/src/galileo/prompts.py b/src/splunk_ao/prompts.py similarity index 99% rename from src/galileo/prompts.py rename to src/splunk_ao/prompts.py index 065c2bf5..ab0f3606 100644 --- a/src/galileo/prompts.py +++ b/src/splunk_ao/prompts.py @@ -2,7 +2,6 @@ import logging from typing import overload -from galileo.config import SplunkAOConfig from galileo.resources.api.prompts import ( create_global_prompt_template_templates_post, delete_global_template_templates_template_id_delete, @@ -28,10 +27,11 @@ UpdatePromptTemplateRequest, ) from galileo.resources.types import Unset -from galileo.schema.message import Message -from galileo.utils.exceptions import APIException -from galileo.utils.projects import resolve_project_id -from galileo.utils.prompts import generate_unique_name +from splunk_ao.config import SplunkAOConfig +from splunk_ao.schema.message import Message +from splunk_ao.utils.exceptions import APIException +from splunk_ao.utils.projects import resolve_project_id +from splunk_ao.utils.prompts import generate_unique_name _logger = logging.getLogger(__name__) diff --git a/src/galileo/protect.py b/src/splunk_ao/protect.py similarity index 98% rename from src/galileo/protect.py rename to src/splunk_ao/protect.py index a5fc4a6f..ed16d0c0 100644 --- a/src/galileo/protect.py +++ b/src/splunk_ao/protect.py @@ -2,8 +2,6 @@ from pydantic import UUID4 -from galileo.config import SplunkAOConfig -from galileo.constants.protect import TIMEOUT_SECS from galileo.resources.api.protect import invoke_protect_invoke_post from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.protect_request import ProtectRequest as APIRequest @@ -13,6 +11,8 @@ from galileo_core.schemas.protect.request import Request from galileo_core.schemas.protect.response import Response from galileo_core.schemas.protect.ruleset import Ruleset +from splunk_ao.config import SplunkAOConfig +from splunk_ao.constants.protect import TIMEOUT_SECS class Protect: diff --git a/src/galileo/provider.py b/src/splunk_ao/provider.py similarity index 99% rename from src/galileo/provider.py rename to src/splunk_ao/provider.py index 8a87ea45..0fc584f1 100644 --- a/src/galileo/provider.py +++ b/src/splunk_ao/provider.py @@ -5,7 +5,6 @@ from datetime import datetime from typing import Any -from galileo.config import SplunkAOConfig from galileo.resources.api.integrations import ( create_or_update_integration_integrations_anthropic_put, create_or_update_integration_integrations_aws_bedrock_put, @@ -24,9 +23,10 @@ OpenAIIntegrationCreate, ) from galileo.resources.types import Unset -from galileo.shared.base import StateManagementMixin, SyncState -from galileo.shared.exceptions import APIError, IntegrationNotConfiguredError, ValidationError -from galileo.utils.exceptions import APIException +from splunk_ao.config import SplunkAOConfig +from splunk_ao.shared.base import StateManagementMixin, SyncState +from splunk_ao.shared.exceptions import APIError, IntegrationNotConfiguredError, ValidationError +from splunk_ao.utils.exceptions import APIException logger = logging.getLogger(__name__) @@ -887,4 +887,4 @@ def __str__(self) -> str: # Import Model here to avoid circular imports -from galileo.model import Model # noqa: E402 +from splunk_ao.model import Model # noqa: E402 diff --git a/src/galileo/runs.py b/src/splunk_ao/runs.py similarity index 97% rename from src/galileo/runs.py rename to src/splunk_ao/runs.py index 92dcbbb2..0ccbd54e 100644 --- a/src/galileo/runs.py +++ b/src/splunk_ao/runs.py @@ -1,6 +1,5 @@ import logging -from galileo.config import SplunkAOConfig from galileo.resources.api.run_scorer_settings import ( upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch, ) @@ -11,6 +10,7 @@ ScorerConfig, SegmentFilter, ) +from splunk_ao.config import SplunkAOConfig logger = logging.getLogger(__name__) diff --git a/src/splunk_ao/schema/__init__.py b/src/splunk_ao/schema/__init__.py new file mode 100644 index 00000000..df0cf045 --- /dev/null +++ b/src/splunk_ao/schema/__init__.py @@ -0,0 +1,14 @@ +# ruff: noqa: F401 +from splunk_ao.schema.content_blocks import DataContentBlock, IngestContentBlock, IngestMessageContent, TextContentBlock +from splunk_ao.schema.logged import ( + IngestInputType, + IngestOutputType, + LoggedAgentSpan, + LoggedControlSpan, + LoggedLlmSpan, + LoggedSpan, + LoggedTrace, + LoggedWorkflowSpan, + TextOrContentBlocks, +) +from splunk_ao.schema.message import LoggedMessage diff --git a/src/galileo/schema/content_blocks.py b/src/splunk_ao/schema/content_blocks.py similarity index 100% rename from src/galileo/schema/content_blocks.py rename to src/splunk_ao/schema/content_blocks.py diff --git a/src/galileo/schema/datasets.py b/src/splunk_ao/schema/datasets.py similarity index 100% rename from src/galileo/schema/datasets.py rename to src/splunk_ao/schema/datasets.py diff --git a/src/galileo/schema/experiment_group.py b/src/splunk_ao/schema/experiment_group.py similarity index 100% rename from src/galileo/schema/experiment_group.py rename to src/splunk_ao/schema/experiment_group.py diff --git a/src/galileo/schema/filters.py b/src/splunk_ao/schema/filters.py similarity index 100% rename from src/galileo/schema/filters.py rename to src/splunk_ao/schema/filters.py diff --git a/src/galileo/schema/handlers.py b/src/splunk_ao/schema/handlers.py similarity index 100% rename from src/galileo/schema/handlers.py rename to src/splunk_ao/schema/handlers.py diff --git a/src/galileo/schema/logged.py b/src/splunk_ao/schema/logged.py similarity index 96% rename from src/galileo/schema/logged.py rename to src/splunk_ao/schema/logged.py index eec25516..6f1b90bb 100644 --- a/src/galileo/schema/logged.py +++ b/src/splunk_ao/schema/logged.py @@ -11,9 +11,6 @@ from pydantic import Field -from galileo.logger.control import ControlSpan -from galileo.schema.content_blocks import IngestContentBlock, IngestMessageContent -from galileo.schema.message import LoggedMessage from galileo_core.schemas.logging.llm import Message, MessageRole from galileo_core.schemas.logging.span import ( AgentSpan, @@ -28,6 +25,9 @@ from galileo_core.schemas.logging.step import BaseStep from galileo_core.schemas.logging.trace import Trace from galileo_core.schemas.shared.document import Document +from splunk_ao.logger.control import ControlSpan +from splunk_ao.schema.content_blocks import IngestContentBlock, IngestMessageContent +from splunk_ao.schema.message import LoggedMessage TextOrContentBlocks = IngestMessageContent IngestInputType = str | Sequence[LoggedMessage] | list[IngestContentBlock] diff --git a/src/galileo/schema/message.py b/src/splunk_ao/schema/message.py similarity index 95% rename from src/galileo/schema/message.py rename to src/splunk_ao/schema/message.py index 20019f9f..bb183ee6 100644 --- a/src/galileo/schema/message.py +++ b/src/splunk_ao/schema/message.py @@ -3,12 +3,12 @@ from pydantic import Field -from galileo.schema.content_blocks import IngestMessageContent from galileo_core.schemas.logging.llm import Message as CoreMessage # These classes should not be removed. They are used to rebuild the new `Message` model # we are defining below. from galileo_core.schemas.logging.llm import ToolCall, ToolCallFunction +from splunk_ao.schema.content_blocks import IngestMessageContent class Message(CoreMessage): diff --git a/src/galileo/schema/metrics.py b/src/splunk_ao/schema/metrics.py similarity index 100% rename from src/galileo/schema/metrics.py rename to src/splunk_ao/schema/metrics.py diff --git a/src/galileo/schema/trace.py b/src/splunk_ao/schema/trace.py similarity index 99% rename from src/galileo/schema/trace.py rename to src/splunk_ao/schema/trace.py index 121b1b8a..5d7b6c5b 100644 --- a/src/galileo/schema/trace.py +++ b/src/splunk_ao/schema/trace.py @@ -4,8 +4,8 @@ from pydantic import UUID4, BaseModel, Field from galileo.resources.models import Document -from galileo.schema.logged import LoggedSpan, LoggedTrace from galileo_core.schemas.logging.step import StepAllowedInputType, StepAllowedOutputType +from splunk_ao.schema.logged import LoggedSpan, LoggedTrace SPAN_TYPE = Literal["llm", "retriever", "tool", "workflow", "agent"] diff --git a/src/galileo/scorers.py b/src/splunk_ao/scorers.py similarity index 99% rename from src/galileo/scorers.py rename to src/splunk_ao/scorers.py index 277b8e35..d05e44da 100644 --- a/src/galileo/scorers.py +++ b/src/splunk_ao/scorers.py @@ -1,7 +1,6 @@ import builtins from uuid import UUID -from galileo.config import SplunkAOConfig from galileo.resources.api.data import ( get_scorer_version_or_latest_scorers_scorer_id_version_get, list_scorers_with_filters_scorers_list_post, @@ -29,6 +28,7 @@ from galileo.resources.models.run_scorer_settings_patch_request import RunScorerSettingsPatchRequest from galileo.resources.models.run_scorer_settings_response import RunScorerSettingsResponse from galileo.resources.types import Unset +from splunk_ao.config import SplunkAOConfig class Scorers: diff --git a/src/galileo/search.py b/src/splunk_ao/search.py similarity index 98% rename from src/galileo/search.py rename to src/splunk_ao/search.py index 6358e979..9b0e9372 100644 --- a/src/galileo/search.py +++ b/src/splunk_ao/search.py @@ -1,7 +1,6 @@ import logging from enum import Enum -from galileo.config import SplunkAOConfig from galileo.resources.api.trace import ( query_sessions_projects_project_id_sessions_search_post, query_spans_projects_project_id_spans_search_post, @@ -13,7 +12,8 @@ LogRecordsQueryResponse, LogRecordsSortClause, ) -from galileo.schema.filters import FilterType +from splunk_ao.config import SplunkAOConfig +from splunk_ao.schema.filters import FilterType logger = logging.getLogger(__name__) diff --git a/src/galileo/shared/__init__.py b/src/splunk_ao/shared/__init__.py similarity index 100% rename from src/galileo/shared/__init__.py rename to src/splunk_ao/shared/__init__.py diff --git a/src/galileo/shared/base.py b/src/splunk_ao/shared/base.py similarity index 100% rename from src/galileo/shared/base.py rename to src/splunk_ao/shared/base.py diff --git a/src/galileo/shared/column.py b/src/splunk_ao/shared/column.py similarity index 99% rename from src/galileo/shared/column.py rename to src/splunk_ao/shared/column.py index 82e37980..658cf7a8 100644 --- a/src/galileo/shared/column.py +++ b/src/splunk_ao/shared/column.py @@ -15,9 +15,9 @@ LogRecordsTextFilter, ) from galileo.resources.types import Unset -from galileo.shared.exceptions import ValidationError -from galileo.shared.filter import boolean, date, number, text -from galileo.shared.sort import sort +from splunk_ao.shared.exceptions import ValidationError +from splunk_ao.shared.filter import boolean, date, number, text +from splunk_ao.shared.sort import sort if TYPE_CHECKING: from galileo.resources.models import ColumnInfo diff --git a/src/galileo/shared/exceptions.py b/src/splunk_ao/shared/exceptions.py similarity index 94% rename from src/galileo/shared/exceptions.py rename to src/splunk_ao/shared/exceptions.py index 694f1743..7533fd73 100644 --- a/src/galileo/shared/exceptions.py +++ b/src/splunk_ao/shared/exceptions.py @@ -1,7 +1,7 @@ from typing import ClassVar -from galileo.exceptions import NotFoundError -from galileo.utils.env_helpers import _get_project_from_env, _get_project_id_from_env +from splunk_ao.exceptions import NotFoundError +from splunk_ao.utils.env_helpers import _get_project_from_env, _get_project_id_from_env class SplunkAOFutureError(Exception): @@ -108,7 +108,7 @@ def __init__(self, integration_name: str): def _normalize_identifier(value: str | None) -> str | None: """Strip and return ``None`` for empty/whitespace-only inputs. - Mirrors the trimming :meth:`galileo.projects.Projects.get` does internally, + Mirrors the trimming :meth:`splunk_ao.projects.Projects.get` does internally, so callers that pre-check identifiers see the same "effectively empty" values the API client would see. """ @@ -121,7 +121,7 @@ def _normalize_identifier(value: str | None) -> str | None: def _resolve_project_identifiers(project_id: str | None, project_name: str | None) -> tuple[str | None, str | None]: """Apply env-fallback precedence to produce a normalized ``(id, name)`` tuple. - Matches the precedence documented by :meth:`galileo.projects.Projects.get_with_env_fallbacks` + Matches the precedence documented by :meth:`splunk_ao.projects.Projects.get_with_env_fallbacks` exactly: explicit ``project_id`` > explicit ``project_name`` > ``SPLUNK_AO_PROJECT_ID`` > ``SPLUNK_AO_PROJECT``. Once an id is chosen, name is dropped; once a name is chosen, env-id is *not* consulted (an explicit name suppresses env-id fallback). @@ -131,7 +131,7 @@ def _resolve_project_identifiers(project_id: str | None, project_name: str | Non from the API client's internal strip-and-validate. Shared by :func:`_project_not_found_error` (uses the result for error-message - context) and :func:`galileo.shared.project_resolver._resolve_project` (uses the + context) and :func:`splunk_ao.shared.project_resolver._resolve_project` (uses the result for both the pre-check and the actual API call). """ explicit_id = _normalize_identifier(project_id) diff --git a/src/galileo/shared/experiment_result.py b/src/splunk_ao/shared/experiment_result.py similarity index 100% rename from src/galileo/shared/experiment_result.py rename to src/splunk_ao/shared/experiment_result.py diff --git a/src/galileo/shared/filter.py b/src/splunk_ao/shared/filter.py similarity index 100% rename from src/galileo/shared/filter.py rename to src/splunk_ao/shared/filter.py diff --git a/src/galileo/shared/project_resolver.py b/src/splunk_ao/shared/project_resolver.py similarity index 75% rename from src/galileo/shared/project_resolver.py rename to src/splunk_ao/shared/project_resolver.py index cb515654..fca8b627 100644 --- a/src/galileo/shared/project_resolver.py +++ b/src/splunk_ao/shared/project_resolver.py @@ -1,6 +1,6 @@ """Shared helper for resolving a project from explicit params or env fallbacks. -Lives alongside :func:`galileo.shared.exceptions._project_not_found_error` so the +Lives alongside :func:`splunk_ao.shared.exceptions._project_not_found_error` so the two helpers — "how to find a project" and "what error to raise when you can't" — sit in one place and can be reused by every ``__future__`` domain object (LogStream, Experiment, …) instead of being duplicated per-class. @@ -8,17 +8,17 @@ from __future__ import annotations -from galileo.projects import Project as ProjectRecord -from galileo.projects import ProjectNotFoundError, Projects -from galileo.shared.exceptions import _project_not_found_error, _resolve_project_identifiers +from splunk_ao.projects import Project as ProjectRecord +from splunk_ao.projects import ProjectNotFoundError, Projects +from splunk_ao.shared.exceptions import _project_not_found_error, _resolve_project_identifiers def _resolve_project(project_id: str | None, project_name: str | None) -> ProjectRecord: """Resolve a project from explicit params or env fallbacks. Identifier precedence and whitespace handling are delegated to - :func:`galileo.shared.exceptions._resolve_project_identifiers`, which matches - the contract of :meth:`galileo.projects.Projects.get_with_env_fallbacks`. + :func:`splunk_ao.shared.exceptions._resolve_project_identifiers`, which matches + the contract of :meth:`splunk_ao.projects.Projects.get_with_env_fallbacks`. Raises ``NotFoundError`` (specifically the ``ResourceNotFoundError`` subclass for backward compat) when no project can be located. Catching either type works. diff --git a/src/galileo/shared/query_result.py b/src/splunk_ao/shared/query_result.py similarity index 98% rename from src/galileo/shared/query_result.py rename to src/splunk_ao/shared/query_result.py index 314f6bc2..4c6e8020 100644 --- a/src/galileo/shared/query_result.py +++ b/src/splunk_ao/shared/query_result.py @@ -11,8 +11,8 @@ if TYPE_CHECKING: from galileo.resources.models import LogRecordsSortClause - from galileo.schema.filters import FilterType - from galileo.search import RecordType + from splunk_ao.schema.filters import FilterType + from splunk_ao.search import RecordType logger = logging.getLogger(__name__) diff --git a/src/galileo/shared/sort.py b/src/splunk_ao/shared/sort.py similarity index 100% rename from src/galileo/shared/sort.py rename to src/splunk_ao/shared/sort.py diff --git a/src/galileo/shared/utils.py b/src/splunk_ao/shared/utils.py similarity index 100% rename from src/galileo/shared/utils.py rename to src/splunk_ao/shared/utils.py diff --git a/src/galileo/stages.py b/src/splunk_ao/stages.py similarity index 99% rename from src/galileo/stages.py rename to src/splunk_ao/stages.py index 31aecb2f..9ccbfb56 100644 --- a/src/galileo/stages.py +++ b/src/splunk_ao/stages.py @@ -2,8 +2,6 @@ from pydantic import UUID4 -from galileo.config import SplunkAOConfig -from galileo.projects import Projects from galileo.resources.api.protect import ( create_stage_projects_project_id_stages_post, get_stage_projects_project_id_stages_get, @@ -17,6 +15,8 @@ from galileo_core.schemas.protect.ruleset import Ruleset, RulesetsMixin from galileo_core.schemas.protect.stage import StageDB, StageType, StageWithRulesets from galileo_core.utils.name import ts_name +from splunk_ao.config import SplunkAOConfig +from splunk_ao.projects import Projects def _get_validated_project_id(project_id: str | UUID4 | None = None, project_name: str | None = None) -> str: diff --git a/src/galileo/traces.py b/src/splunk_ao/traces.py similarity index 97% rename from src/galileo/traces.py rename to src/splunk_ao/traces.py index 4cf61292..e314a19e 100644 --- a/src/galileo/traces.py +++ b/src/splunk_ao/traces.py @@ -5,9 +5,11 @@ import httpx -from galileo.config import SplunkAOConfig -from galileo.constants.routes import Routes -from galileo.schema.trace import ( +from galileo_core.constants.http_headers import HttpHeaders +from galileo_core.constants.request_method import RequestMethod +from splunk_ao.config import SplunkAOConfig +from splunk_ao.constants.routes import Routes +from splunk_ao.schema.trace import ( LogRecordsSearchRequest, SessionCreateRequest, SpansIngestRequest, @@ -15,10 +17,8 @@ TracesIngestRequest, TraceUpdateRequest, ) -from galileo.utils.decorators import async_warn_catch_exception -from galileo.utils.headers_data import get_sdk_header -from galileo_core.constants.http_headers import HttpHeaders -from galileo_core.constants.request_method import RequestMethod +from splunk_ao.utils.decorators import async_warn_catch_exception +from splunk_ao.utils.headers_data import get_sdk_header _logger = logging.getLogger(__name__) diff --git a/src/galileo/tracing.py b/src/splunk_ao/tracing.py similarity index 92% rename from src/galileo/tracing.py rename to src/splunk_ao/tracing.py index 562c7a81..96d6a3c2 100644 --- a/src/galileo/tracing.py +++ b/src/splunk_ao/tracing.py @@ -1,6 +1,6 @@ """Utilities for distributed tracing with Galileo.""" -from galileo.decorator import galileo_context +from splunk_ao.decorator import galileo_context def get_tracing_headers() -> dict[str, str]: @@ -25,7 +25,7 @@ def get_tracing_headers() -> dict[str, str]: Using with decorators to propagate trace context to downstream services: ```python - from galileo import log, get_tracing_headers + from splunk_ao import log, get_tracing_headers import httpx @log() diff --git a/src/galileo/types.py b/src/splunk_ao/types.py similarity index 82% rename from src/galileo/types.py rename to src/splunk_ao/types.py index 40d1b495..eec93cd6 100644 --- a/src/galileo/types.py +++ b/src/splunk_ao/types.py @@ -5,8 +5,8 @@ and other Galileo objects. """ -from galileo.metric import Metric -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig +from splunk_ao.metric import Metric +from splunk_ao.schema.metrics import LocalMetricConfig, SplunkAOMetrics # Unified metric type that accepts all valid metric specifications MetricSpec = ( diff --git a/src/splunk_ao/utils/__init__.py b/src/splunk_ao/utils/__init__.py new file mode 100644 index 00000000..4cc0e5fe --- /dev/null +++ b/src/splunk_ao/utils/__init__.py @@ -0,0 +1,9 @@ +from datetime import datetime, timezone + + +def _get_timestamp() -> datetime: + return datetime.now(timezone.utc) + + +def _now_ns() -> int: + return round(_get_timestamp().timestamp() * 1e9) diff --git a/src/galileo/utils/datasets.py b/src/splunk_ao/utils/datasets.py similarity index 95% rename from src/galileo/utils/datasets.py rename to src/splunk_ao/utils/datasets.py index 002f0b03..a9984aee 100644 --- a/src/galileo/utils/datasets.py +++ b/src/splunk_ao/utils/datasets.py @@ -1,12 +1,12 @@ from typing import TYPE_CHECKING, Any, Optional, Union -from galileo.config import SplunkAOConfig from galileo.resources.models.dataset_content import DatasetContent from galileo.resources.types import Unset -from galileo.schema.datasets import DatasetRecord +from splunk_ao.config import SplunkAOConfig +from splunk_ao.schema.datasets import DatasetRecord if TYPE_CHECKING: - from galileo.datasets import Dataset + from splunk_ao.datasets import Dataset def remap_output_to_ground_truth(content: DatasetContent) -> DatasetContent: @@ -91,7 +91,7 @@ def load_dataset( ValueError If no dataset information is provided or dataset doesn't exist """ - from galileo.datasets import get_dataset + from splunk_ao.datasets import get_dataset if dataset_id: return get_dataset(id=dataset_id) @@ -146,7 +146,7 @@ def load_dataset_and_records( def get_dataset_and_records(id: str | None = None, name: str | None = None) -> tuple["Dataset", list[DatasetRecord]]: - from galileo.datasets import get_dataset + from splunk_ao.datasets import get_dataset if id: dataset = get_dataset(id=id) @@ -163,7 +163,7 @@ def get_dataset_and_records(id: str | None = None, name: str | None = None) -> t def get_records_for_dataset(dataset: "Dataset") -> list[DatasetRecord]: - from galileo.datasets import convert_dataset_row_to_record + from splunk_ao.datasets import convert_dataset_row_to_record content = dataset.get_content() if not content: diff --git a/src/galileo/utils/decorators/__init__.py b/src/splunk_ao/utils/decorators/__init__.py similarity index 79% rename from src/galileo/utils/decorators/__init__.py rename to src/splunk_ao/utils/decorators/__init__.py index fe58bd18..1bb002f2 100644 --- a/src/galileo/utils/decorators/__init__.py +++ b/src/splunk_ao/utils/decorators/__init__.py @@ -7,14 +7,14 @@ - Conditional execution based on telemetry toggle """ -from galileo.utils.decorators.exception_handling import ( +from splunk_ao.utils.decorators.exception_handling import ( INFRASTRUCTURE_EXCEPTIONS, RETRYABLE_STATUS_CODES, async_warn_catch_exception, retry_on_transient_http_error, warn_catch_exception, ) -from galileo.utils.decorators.telemetry_toggle import galileo_logging_enabled, nop_async, nop_sync +from splunk_ao.utils.decorators.telemetry_toggle import galileo_logging_enabled, nop_async, nop_sync __all__ = [ "INFRASTRUCTURE_EXCEPTIONS", diff --git a/src/galileo/utils/decorators/exception_handling.py b/src/splunk_ao/utils/decorators/exception_handling.py similarity index 100% rename from src/galileo/utils/decorators/exception_handling.py rename to src/splunk_ao/utils/decorators/exception_handling.py diff --git a/src/galileo/utils/decorators/telemetry_toggle.py b/src/splunk_ao/utils/decorators/telemetry_toggle.py similarity index 100% rename from src/galileo/utils/decorators/telemetry_toggle.py rename to src/splunk_ao/utils/decorators/telemetry_toggle.py diff --git a/src/galileo/utils/dependencies.py b/src/splunk_ao/utils/dependencies.py similarity index 100% rename from src/galileo/utils/dependencies.py rename to src/splunk_ao/utils/dependencies.py diff --git a/src/galileo/utils/env_helpers.py b/src/splunk_ao/utils/env_helpers.py similarity index 95% rename from src/galileo/utils/env_helpers.py rename to src/splunk_ao/utils/env_helpers.py index 3bf51b3c..6e522f98 100644 --- a/src/galileo/utils/env_helpers.py +++ b/src/splunk_ao/utils/env_helpers.py @@ -2,8 +2,8 @@ from os import getenv -from galileo.constants import DEFAULT_LOG_STREAM_NAME, DEFAULT_MODE, DEFAULT_PROJECT_NAME, LoggerModeType -from galileo.exceptions import SplunkAOLoggerException +from splunk_ao.constants import DEFAULT_LOG_STREAM_NAME, DEFAULT_MODE, DEFAULT_PROJECT_NAME, LoggerModeType +from splunk_ao.exceptions import SplunkAOLoggerException def _get_mode_or_default(mode: str | None) -> LoggerModeType: diff --git a/src/galileo/utils/exceptions.py b/src/splunk_ao/utils/exceptions.py similarity index 100% rename from src/galileo/utils/exceptions.py rename to src/splunk_ao/utils/exceptions.py diff --git a/src/splunk_ao/utils/headers_data.py b/src/splunk_ao/utils/headers_data.py new file mode 100644 index 00000000..2be9024b --- /dev/null +++ b/src/splunk_ao/utils/headers_data.py @@ -0,0 +1,72 @@ +import inspect +from importlib.metadata import PackageNotFoundError, version +from typing import Any + + +def get_package_version() -> str: + """Get the installed SDK distribution version.""" + try: + return version("galileo") + except PackageNotFoundError: + return "0.0.0" # Unknown version + + +def get_method_name() -> str: + """Get the entry point method name into the SDK namespace boundary. + + Returns the last SDK function before exiting the supported namespace boundary + when traversing from the bottom of the call stack. This captures entry points + from the active ``splunk_ao`` package and from protected generated resources + that remain under ``galileo.resources`` for HYBIM-717. + + Returns + ------- + str + A string in format "{function_name}@{module_name}" or empty string if not found. + """ + frame = inspect.currentframe() + try: + # Collect all frames + frames_info: list[dict[str, Any]] = [] + temp_frame = frame + while temp_frame is not None: + module = inspect.getmodule(temp_frame) + module_name: str = module.__name__ if module else "" + function_name: str = temp_frame.f_code.co_name + filename: str = temp_frame.f_code.co_filename + lineno: int = temp_frame.f_lineno + + frames_info.append({"module": module_name, "function": function_name, "file": filename, "line": lineno}) + temp_frame = temp_frame.f_back + + # Find the entry point into the SDK package (traversing from bottom to top). + # Protected generated resources remain under galileo.resources for HYBIM-717. + entry_point: dict[str, Any] | None = None + for i in range(len(frames_info) - 1, -1, -1): + frame_info = frames_info[i] + module_name = str(frame_info["module"]) # Explicitly cast to string + + if module_name.startswith(("splunk_ao.", "galileo.resources.")): + entry_point = frame_info + break + + # Return the formatted method name + if entry_point: + return f"{entry_point['function']}@{entry_point['module']}" + + return "" + finally: + # Clean up frame references to avoid reference cycles + del frame + + +def get_sdk_header() -> str: + """Build the X-Galileo-SDK header value.""" + version = get_package_version() + method_name = get_method_name() + + sdk_header = f"galileo-python/{version}" + if method_name: + sdk_header = f"{sdk_header} {method_name}" + + return sdk_header diff --git a/src/galileo/utils/log_config.py b/src/splunk_ao/utils/log_config.py similarity index 89% rename from src/galileo/utils/log_config.py rename to src/splunk_ao/utils/log_config.py index 0c72ad7e..e7b9b745 100644 --- a/src/galileo/utils/log_config.py +++ b/src/splunk_ao/utils/log_config.py @@ -7,6 +7,8 @@ import logging +SDK_LOGGER_NAME = "splunk_ao" + def _is_logger_configured(logger: logging.Logger) -> bool: """ @@ -29,10 +31,10 @@ def _is_logger_configured(logger: logging.Logger) -> bool: def _ensure_silent_by_default() -> None: """ - Ensure galileo loggers are silent by default, but only if they haven't been configured yet. + Ensure SDK loggers are silent by default, but only if they haven't been configured yet. This avoids interfering with existing logging configurations. """ - logger = logging.getLogger("galileo") + logger = logging.getLogger(SDK_LOGGER_NAME) # Only apply silent defaults if the logger hasn't been configured by the user if not _is_logger_configured(logger): @@ -67,7 +69,7 @@ def enable_console_logging(level: int = logging.INFO) -> None: """ Enable console logging for interactive use. - This function configures the root galileo logger to output to the console + This function configures the root SDK logger to output to the console with a simple formatter. This is particularly useful for REPL, IPython, and Jupyter environments where users want to see SDK logs immediately. @@ -78,14 +80,14 @@ def enable_console_logging(level: int = logging.INFO) -> None: Examples -------- - >>> import galileo - >>> galileo.enable_console_logging() + >>> import splunk_ao + >>> splunk_ao.enable_console_logging() >>> # Now SDK operations will show progress and debug information """ # Ensure we apply silent defaults first if logger wasn't configured _ensure_silent_by_default() - logger = logging.getLogger("galileo") + logger = logging.getLogger(SDK_LOGGER_NAME) # Check if handler already exists to avoid duplicates if not any(isinstance(handler, logging.StreamHandler) for handler in logger.handlers): diff --git a/src/galileo/utils/metrics.py b/src/splunk_ao/utils/metrics.py similarity index 98% rename from src/galileo/utils/metrics.py rename to src/splunk_ao/utils/metrics.py index 3be2daa2..2518d072 100644 --- a/src/galileo/utils/metrics.py +++ b/src/splunk_ao/utils/metrics.py @@ -6,11 +6,11 @@ from galileo.resources.models.scorer_config import ScorerConfig from galileo.resources.models.scorer_response import ScorerResponse -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig, Metric -from galileo.scorers import Scorers, ScorerSettings from galileo_core.schemas.logging.span import Span, StepWithChildSpans from galileo_core.schemas.logging.trace import Trace from galileo_core.schemas.shared.metric import MetricValueType +from splunk_ao.schema.metrics import LocalMetricConfig, Metric, SplunkAOMetrics +from splunk_ao.scorers import Scorers, ScorerSettings logger = logging.getLogger(__name__) diff --git a/src/galileo/utils/openai_agents.py b/src/splunk_ao/utils/openai_agents.py similarity index 99% rename from src/galileo/utils/openai_agents.py rename to src/splunk_ao/utils/openai_agents.py index f4856a14..1c7a24be 100644 --- a/src/galileo/utils/openai_agents.py +++ b/src/splunk_ao/utils/openai_agents.py @@ -13,9 +13,9 @@ ) from agents.tracing import ResponseSpanData -from galileo.schema.handlers import SPAN_TYPE -from galileo.utils.serialization import serialize_to_str from galileo_core.schemas.logging.span import Span as GalileoSpan +from splunk_ao.schema.handlers import SPAN_TYPE +from splunk_ao.utils.serialization import serialize_to_str _logger = logging.getLogger(__name__) diff --git a/src/galileo/utils/projects.py b/src/splunk_ao/utils/projects.py similarity index 97% rename from src/galileo/utils/projects.py rename to src/splunk_ao/utils/projects.py index 7067450c..1eb8adc5 100644 --- a/src/galileo/utils/projects.py +++ b/src/splunk_ao/utils/projects.py @@ -1,6 +1,6 @@ """Utility functions for project operations.""" -from galileo.projects import Projects +from splunk_ao.projects import Projects def resolve_project_id( diff --git a/src/galileo/utils/prompts.py b/src/splunk_ao/utils/prompts.py similarity index 97% rename from src/galileo/utils/prompts.py rename to src/splunk_ao/utils/prompts.py index d128e325..3cffac7f 100644 --- a/src/galileo/utils/prompts.py +++ b/src/splunk_ao/utils/prompts.py @@ -26,7 +26,7 @@ def check_name_exists_in_organization(name: str) -> bool: True if the name exists, False otherwise. """ # Import here to avoid circular dependency - from galileo.prompts import GlobalPromptTemplates + from splunk_ao.prompts import GlobalPromptTemplates # Check global templates global_templates = GlobalPromptTemplates().list(name_filter=name, limit=1000) diff --git a/src/galileo/utils/retrievers.py b/src/splunk_ao/utils/retrievers.py similarity index 93% rename from src/galileo/utils/retrievers.py rename to src/splunk_ao/utils/retrievers.py index d88b0e8d..aad67434 100644 --- a/src/galileo/utils/retrievers.py +++ b/src/splunk_ao/utils/retrievers.py @@ -3,9 +3,9 @@ from pydantic import TypeAdapter, ValidationError -from galileo.schema.trace import Document as GalileoDocument -from galileo.schema.trace import RetrieverSpanAllowedOutputType from galileo_core.schemas.shared.document import Document +from splunk_ao.schema.trace import Document as GalileoDocument +from splunk_ao.schema.trace import RetrieverSpanAllowedOutputType document_adapter = TypeAdapter(list[Document]) diff --git a/src/galileo/utils/serialization.py b/src/splunk_ao/utils/serialization.py similarity index 99% rename from src/galileo/utils/serialization.py rename to src/splunk_ao/utils/serialization.py index 9404cf79..4cf69a2e 100644 --- a/src/galileo/utils/serialization.py +++ b/src/splunk_ao/utils/serialization.py @@ -14,7 +14,7 @@ from pydantic import BaseModel -from galileo.utils.dependencies import is_langchain_available, is_langgraph_available, is_proto_plus_available +from splunk_ao.utils.dependencies import is_langchain_available, is_langgraph_available, is_proto_plus_available _logger = logging.getLogger(__name__) diff --git a/src/galileo/utils/singleton.py b/src/splunk_ao/utils/singleton.py similarity index 98% rename from src/galileo/utils/singleton.py rename to src/splunk_ao/utils/singleton.py index 1ec57623..ef692eb7 100644 --- a/src/galileo/utils/singleton.py +++ b/src/splunk_ao/utils/singleton.py @@ -3,9 +3,9 @@ from collections.abc import Callable from typing import ClassVar -from galileo.logger import SplunkAOLogger -from galileo.schema.metrics import LocalMetricConfig -from galileo.utils.env_helpers import _get_log_stream_or_default, _get_mode_or_default, _get_project_or_default +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.metrics import LocalMetricConfig +from splunk_ao.utils.env_helpers import _get_log_stream_or_default, _get_mode_or_default, _get_project_or_default _logger = logging.getLogger(__name__) diff --git a/src/galileo/utils/span_utils.py b/src/splunk_ao/utils/span_utils.py similarity index 94% rename from src/galileo/utils/span_utils.py rename to src/splunk_ao/utils/span_utils.py index e40e0335..924151cb 100644 --- a/src/galileo/utils/span_utils.py +++ b/src/splunk_ao/utils/span_utils.py @@ -1,6 +1,6 @@ """Utilities for working with span types.""" -from galileo.schema.trace import SPAN_TYPE +from splunk_ao.schema.trace import SPAN_TYPE def is_textual_span_type(span_type: SPAN_TYPE) -> bool: diff --git a/src/galileo/utils/uuid_utils.py b/src/splunk_ao/utils/uuid_utils.py similarity index 100% rename from src/galileo/utils/uuid_utils.py rename to src/splunk_ao/utils/uuid_utils.py diff --git a/src/galileo/utils/validations.py b/src/splunk_ao/utils/validations.py similarity index 96% rename from src/galileo/utils/validations.py rename to src/splunk_ao/utils/validations.py index 6e7aed5e..c4ae288f 100644 --- a/src/galileo/utils/validations.py +++ b/src/splunk_ao/utils/validations.py @@ -2,7 +2,7 @@ from functools import wraps from typing import Any, TypeVar -from galileo.shared.exceptions import ValidationError +from splunk_ao.shared.exceptions import ValidationError R = TypeVar("R") diff --git a/tasks.py b/tasks.py index 5f009c73..3b2cb582 100644 --- a/tasks.py +++ b/tasks.py @@ -21,26 +21,26 @@ def setup(ctx: Context) -> None: @task def test_report_xml(ctx: Context) -> None: - ctx.run("poetry run pytest -vvv --cov=galileo --cov-report=xml", **COMMON_PARAMS) + ctx.run("poetry run pytest -vvv --cov=splunk_ao --cov-report=xml", **COMMON_PARAMS) @task def test(ctx: Context) -> None: - ctx.run("poetry run pytest --cov=galileo --cov-report=term-missing", **COMMON_PARAMS) + ctx.run("poetry run pytest --cov=splunk_ao --cov-report=term-missing", **COMMON_PARAMS) @task def type_check(ctx: Context) -> None: ctx.run( - "poetry run mypy --package galileo " + "poetry run mypy --package splunk_ao " # TODO: remove as soon as mypy errors fixed "--exclude galileo.resources " - "--exclude galileo.openai " - "--exclude galileo.decorator " - "--exclude galileo.handlers.langchain " - "--exclude galileo.log_streams " - "--exclude galileo.logger " - "--exclude galileo.api_client " + "--exclude splunk_ao.openai " + "--exclude splunk_ao.decorator " + "--exclude splunk_ao.handlers.langchain " + "--exclude splunk_ao.log_streams " + "--exclude splunk_ao.logger " + "--exclude splunk_ao.api_client " "--namespace-packages", **COMMON_PARAMS, ) diff --git a/test_support/config.py b/test_support/config.py index d10bcdf3..61b4fce1 100644 --- a/test_support/config.py +++ b/test_support/config.py @@ -1,6 +1,6 @@ -"""Fast GalileoPythonConfig validation for tests. +"""Fast SplunkAOConfig validation for tests. -Building ``GalileoPythonConfig`` runs 3 async validation requests +Building ``SplunkAOConfig`` runs 3 async validation requests (healthcheck/login/current_user) through galileo_core's ``async_run`` / ``EventLoopThreadPool``, whose Windows IOCP poll is ~11x slower on Python 3.11+. In tests these endpoints are already mocked, so they add no coverage — @@ -40,7 +40,7 @@ def fast_validation_payload(endpoint: Any) -> dict: @contextmanager def fast_config_validation() -> Generator[None, None, None]: """Stub the async config-validation round-trips with canned, await-free - results so the per-test ``GalileoPythonConfig`` build is cheap. + results so the per-test ``SplunkAOConfig`` build is cheap. Scoped to the config build only; test bodies still exercise the real validation/connect code. diff --git a/tests/conftest.py b/tests/conftest.py index 28165f0b..797eea38 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,7 +35,7 @@ # background tasks pending, which causes pytest workers to hang at exit. # Override the module constant directly so tests don't depend on a user-facing # env var or any new SDK config knob. -from galileo.logger import logger as _galileo_logger_module # noqa: E402 +from splunk_ao.logger import logger as _galileo_logger_module # noqa: E402 _galileo_logger_module.DEFAULT_TERMINATE_TIMEOUT_SECONDS = 2 @@ -52,9 +52,6 @@ from httpx import Response as HttpxResponse # noqa: E402 from test_support.config import fast_config_validation # noqa: E402 -from galileo.collaborator import CollaboratorRole # noqa: E402 -from galileo.config import SplunkAOConfig # noqa: E402 -from galileo.configuration import _CONFIGURATION_KEYS, Configuration # noqa: E402 from galileo.resources.models import DatasetContent, DatasetRow, DatasetRowValuesDict # noqa: E402 from galileo.resources.models.messages_list_item import MessagesListItem # noqa: E402 from galileo_core.constants.request_method import RequestMethod # noqa: E402 @@ -63,6 +60,9 @@ from galileo_core.schemas.core.user_role import UserRole # noqa: E402 from galileo_core.schemas.protect.rule import Rule, RuleOperator # noqa: E402 from galileo_core.schemas.protect.ruleset import Ruleset # noqa: E402 +from splunk_ao.collaborator import CollaboratorRole # noqa: E402 +from splunk_ao.config import SplunkAOConfig # noqa: E402 +from splunk_ao.configuration import _CONFIGURATION_KEYS, Configuration # noqa: E402 from tests.testutils.setup import setup_thread_pool_request_capture # noqa: E402 # Note: The mock_request fixture is automatically provided by galileo_core[testing] extras @@ -107,7 +107,7 @@ def reset_agent_control_bridge_state() -> Generator[None, None, None]: """Reset optional Agent Control bridge globals when tests load that module.""" yield - bridge_module = sys.modules.get("galileo.handlers.agent_control.bridge") + bridge_module = sys.modules.get("splunk_ao.handlers.agent_control.bridge") if bridge_module is None: return @@ -337,8 +337,8 @@ def rulesets(request: pytest.FixtureRequest) -> list[Ruleset]: @pytest.fixture def enable_galileo_logging(): - """Temporarily enable galileo logging for tests that need to capture log output.""" - galileo_logger = logging.getLogger("galileo") + """Temporarily enable SDK logging for tests that need to capture log output.""" + galileo_logger = logging.getLogger("splunk_ao") original_level = galileo_logger.level original_propagate = galileo_logger.propagate @@ -396,8 +396,8 @@ def mock_env_file(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: @pytest.fixture def capture_logs() -> Generator[tuple[logging.Logger, StringIO], None, None]: - """Capture log messages emitted by the galileo logger for assertion.""" - logger = logging.getLogger("galileo") + """Capture log messages emitted by the SDK logger for assertion.""" + logger = logging.getLogger("splunk_ao") original_level = logger.level original_handlers = logger.handlers[:] original_propagate = logger.propagate diff --git a/tests/schemas/test_datasets.py b/tests/schemas/test_datasets.py index 1fe1262a..50e0acb3 100644 --- a/tests/schemas/test_datasets.py +++ b/tests/schemas/test_datasets.py @@ -2,7 +2,7 @@ import pytest -from galileo.schema.datasets import DatasetRecord +from splunk_ao.schema.datasets import DatasetRecord class TestDatasetRecordValidators: diff --git a/tests/schemas/test_logged.py b/tests/schemas/test_logged.py index 48677170..3299eeaf 100644 --- a/tests/schemas/test_logged.py +++ b/tests/schemas/test_logged.py @@ -6,18 +6,18 @@ import pytest from pydantic import ValidationError -import galileo.logger.control as control_module -import galileo.logger.logger as logger_module -import galileo.schema.logged as logged_module -from galileo.schema.content_blocks import DataContentBlock, TextContentBlock -from galileo.schema.logged import LoggedAgentSpan, LoggedControlSpan, LoggedLlmSpan, LoggedTrace, LoggedWorkflowSpan -from galileo.schema.message import LoggedMessage -from galileo.schema.trace import TracesIngestRequest +import splunk_ao.logger.control as control_module +import splunk_ao.logger.logger as logger_module +import splunk_ao.schema.logged as logged_module from galileo_core.schemas.logging.llm import MessageRole from galileo_core.schemas.logging.span import AgentSpan, LlmSpan, RetrieverSpan, ToolSpan, WorkflowSpan from galileo_core.schemas.logging.trace import Trace from galileo_core.schemas.shared.document import Document from galileo_core.schemas.shared.multimodal import ContentModality +from splunk_ao.schema.content_blocks import DataContentBlock, TextContentBlock +from splunk_ao.schema.logged import LoggedAgentSpan, LoggedControlSpan, LoggedLlmSpan, LoggedTrace, LoggedWorkflowSpan +from splunk_ao.schema.message import LoggedMessage +from splunk_ao.schema.trace import TracesIngestRequest class TestTextContentBlock: @@ -342,7 +342,7 @@ def test_full_ingest_request_roundtrip(self) -> None: assert tool.output == "4" def test_logged_trace_roundtrip_with_fallback_control_span(self, monkeypatch: pytest.MonkeyPatch) -> None: - # Given: galileo.logger.control is reloaded without native ControlSpan support + # Given: splunk_ao.logger.control is reloaded without native ControlSpan support if not control_module.HAS_NATIVE_CONTROL_SPAN: control_payload = control_module.ControlSpan(input="selected text").model_dump(mode="python") trace = logged_module.LoggedTrace(input="query", spans=[control_payload]) @@ -385,7 +385,7 @@ def force_fallback_import(name, globals=None, locals=None, fromlist=(), level=0) def test_fallback_control_span_rejects_non_uuidish_id_fields( self, field_name: str, monkeypatch: pytest.MonkeyPatch ) -> None: - # Given: galileo.logger.control is reloaded without native ControlSpan support + # Given: splunk_ao.logger.control is reloaded without native ControlSpan support if not control_module.HAS_NATIVE_CONTROL_SPAN: with pytest.raises(ValidationError): control_module.ControlSpan(input="selected text", **{field_name: 123}) diff --git a/tests/schemas/test_message.py b/tests/schemas/test_message.py index 12c548b3..c68c219e 100644 --- a/tests/schemas/test_message.py +++ b/tests/schemas/test_message.py @@ -2,7 +2,7 @@ import pytest -from galileo import Message, MessageRole, ToolCall, ToolCallFunction +from splunk_ao import Message, MessageRole, ToolCall, ToolCallFunction @pytest.mark.parametrize( diff --git a/tests/schemas/test_metrics.py b/tests/schemas/test_metrics.py index 83297a82..c8b0451d 100644 --- a/tests/schemas/test_metrics.py +++ b/tests/schemas/test_metrics.py @@ -1,4 +1,4 @@ -from galileo.schema.metrics import SplunkAOMetrics, Metric +from splunk_ao.schema.metrics import Metric, SplunkAOMetrics def test_metric_custom_with_version() -> None: diff --git a/tests/shared/test_project_resolver.py b/tests/shared/test_project_resolver.py index edf55d1a..f072926c 100644 --- a/tests/shared/test_project_resolver.py +++ b/tests/shared/test_project_resolver.py @@ -1,4 +1,4 @@ -"""Unit tests for ``galileo.shared.project_resolver._resolve_project``. +"""Unit tests for ``splunk_ao.shared.project_resolver._resolve_project``. The resolver is the single canonical entry point used by every ``__future__`` domain object (LogStream, Experiment, …) to turn explicit kwargs / env vars @@ -10,16 +10,16 @@ import pytest -from galileo.exceptions import NotFoundError -from galileo.projects import ProjectNotFoundError -from galileo.shared.exceptions import ResourceNotFoundError -from galileo.shared.project_resolver import _resolve_project +from splunk_ao.exceptions import NotFoundError +from splunk_ao.projects import ProjectNotFoundError +from splunk_ao.shared.exceptions import ResourceNotFoundError +from splunk_ao.shared.project_resolver import _resolve_project class TestResolveProject: """Behavioral tests for the shared ``_resolve_project`` helper.""" - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_returns_project_when_get_with_env_fallbacks_succeeds(self, mock_projects_class: MagicMock) -> None: # Given: an explicit project_id that resolves to a known project mock_project = MagicMock() @@ -36,7 +36,7 @@ def test_returns_project_when_get_with_env_fallbacks_succeeds(self, mock_project assert resolved is mock_project mock_service.get_with_env_fallbacks.assert_called_once_with(id="p-1", name=None) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_short_circuits_when_no_identifier_anywhere( self, mock_projects_class: MagicMock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -50,7 +50,7 @@ def test_short_circuits_when_no_identifier_anywhere( _resolve_project(project_id=None, project_name=None) mock_projects_class.assert_not_called() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_returns_resource_not_found_subclass( self, mock_projects_class: MagicMock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -64,7 +64,7 @@ def test_returns_resource_not_found_subclass( _resolve_project(project_id=None, project_name=None) assert isinstance(exc_info.value, ResourceNotFoundError) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_converts_project_not_found_error_to_not_found_error(self, mock_projects_class: MagicMock) -> None: # Given: an explicit id that the API reports as not found mock_service = MagicMock() @@ -75,7 +75,7 @@ def test_converts_project_not_found_error_to_not_found_error(self, mock_projects with pytest.raises(NotFoundError, match='Project with id "missing-id" not found'): _resolve_project(project_id="missing-id", project_name=None) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_does_not_swallow_unrelated_value_error(self, mock_projects_class: MagicMock) -> None: """Unrelated ValueErrors from the API client surface unchanged.""" # Given: the API client raises a generic ValueError (e.g. deserialization) @@ -87,7 +87,7 @@ def test_does_not_swallow_unrelated_value_error(self, mock_projects_class: Magic with pytest.raises(ValueError, match="response decode failed"): _resolve_project(project_id="some-id", project_name=None) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_raises_not_found_when_get_with_env_fallbacks_returns_none(self, mock_projects_class: MagicMock) -> None: # Given: get_with_env_fallbacks returns None (project not found, no exception) mock_service = MagicMock() @@ -98,7 +98,7 @@ def test_raises_not_found_when_get_with_env_fallbacks_returns_none(self, mock_pr with pytest.raises(NotFoundError, match='Project "Missing"'): _resolve_project(project_id=None, project_name="Missing") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_whitespace_only_explicit_args_treated_as_missing( self, mock_projects_class: MagicMock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -117,7 +117,7 @@ def test_whitespace_only_explicit_args_treated_as_missing( _resolve_project(project_id=" ", project_name="\t\n") mock_projects_class.assert_not_called() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_whitespace_only_env_vars_treated_as_missing( self, mock_projects_class: MagicMock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -136,7 +136,7 @@ def test_whitespace_only_env_vars_treated_as_missing( _resolve_project(project_id=None, project_name=None) mock_projects_class.assert_not_called() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_strips_whitespace_around_valid_identifier(self, mock_projects_class: MagicMock) -> None: """A valid identifier with surrounding whitespace is trimmed before delegation.""" # Given: a project that resolves successfully @@ -154,7 +154,7 @@ def test_strips_whitespace_around_valid_identifier(self, mock_projects_class: Ma assert resolved is mock_project mock_service.get_with_env_fallbacks.assert_called_once_with(id=None, name="P One") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_explicit_name_suppresses_env_id_fallback( self, mock_projects_class: MagicMock, monkeypatch: pytest.MonkeyPatch ) -> None: diff --git a/tests/test_agent_control.py b/tests/test_agent_control.py index 9e251258..5e743959 100644 --- a/tests/test_agent_control.py +++ b/tests/test_agent_control.py @@ -4,10 +4,10 @@ import pytest -from galileo import AgentControlTarget, AgentControlTargetUnresolvedError, get_agent_control_target -from galileo.constants import DEFAULT_LOG_STREAM_NAME, DEFAULT_PROJECT_NAME -from galileo.decorator import galileo_context -from galileo.utils.singleton import SplunkAOLoggerSingleton +from splunk_ao import AgentControlTarget, AgentControlTargetUnresolvedError, get_agent_control_target +from splunk_ao.constants import DEFAULT_LOG_STREAM_NAME, DEFAULT_PROJECT_NAME +from splunk_ao.decorator import galileo_context +from splunk_ao.utils.singleton import SplunkAOLoggerSingleton @pytest.fixture(autouse=True) diff --git a/tests/test_agent_control_bridge.py b/tests/test_agent_control_bridge.py index dc94d3c9..116c6fde 100644 --- a/tests/test_agent_control_bridge.py +++ b/tests/test_agent_control_bridge.py @@ -13,13 +13,13 @@ import pytest -import galileo.logger.control as control_module -import galileo.logger.logger as logger_module -import galileo.schema.logged as logged_module -from galileo.handlers.agent_control import setup_agent_control_bridge -from galileo.logger.control import ControlResult, ControlSpan -from galileo.logger.logger import SplunkAOLogger -from galileo.schema.trace import SpansIngestRequest, TracesIngestRequest +import splunk_ao.logger.control as control_module +import splunk_ao.logger.logger as logger_module +import splunk_ao.schema.logged as logged_module +from splunk_ao.handlers.agent_control import setup_agent_control_bridge +from splunk_ao.logger.control import ControlResult, ControlSpan +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.schema.trace import SpansIngestRequest, TracesIngestRequest from tests.testutils.setup import ( setup_mock_logstreams_client, setup_mock_projects_client, @@ -103,7 +103,7 @@ def get_trace_context_from_provider(): yield {"agent_control": agent_control_module, "trace_context": trace_context_module, "sinks": sinks_module} - bridge_module = sys.modules.get("galileo.handlers.agent_control.bridge") + bridge_module = sys.modules.get("splunk_ao.handlers.agent_control.bridge") if bridge_module is not None: bridge_module._REGISTERED_BRIDGES.clear() bridge_module._PREVIOUS_TRACE_CONTEXT_PROVIDER = None @@ -144,9 +144,9 @@ def _make_event(logger: SplunkAOLogger, **overrides: object) -> FakeControlExecu return FakeControlExecutionEvent(**payload) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_enable_agent_control_registers_provider_and_sink( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -176,9 +176,9 @@ def test_enable_agent_control_registers_provider_and_sink( assert fake_agent_control_modules["trace_context"].get_trace_context_from_provider() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_auto_registers_agent_control_bridge_when_available( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -196,9 +196,9 @@ def test_logger_auto_registers_agent_control_bridge_when_available( assert fake_agent_control_modules["agent_control"]._registered_sinks == [bridge._sink] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_does_not_raise_when_agent_control_is_missing( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -207,7 +207,7 @@ def test_logger_init_does_not_raise_when_agent_control_is_missing( setup_mock_projects_client(mock_projects_client) setup_mock_logstreams_client(mock_logstreams_client) monkeypatch.setattr( - "galileo.handlers.agent_control.bridge._import_module", lambda name: (_ for _ in ()).throw(ImportError(name)) + "splunk_ao.handlers.agent_control.bridge._import_module", lambda name: (_ for _ in ()).throw(ImportError(name)) ) # When: creating a new Galileo logger @@ -217,9 +217,9 @@ def test_logger_init_does_not_raise_when_agent_control_is_missing( assert getattr(logger, "_agent_control_bridge", None) is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_cleanup_restores_previous_provider_across_loggers( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -262,9 +262,9 @@ def external_provider(): } -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_cleanup_does_not_clobber_provider_installed_while_active( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -295,9 +295,9 @@ def replacement_provider(): assert fake_agent_control_modules["agent_control"]._registered_sinks == [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_idle_new_logger_does_not_mask_active_logger_context( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -327,9 +327,9 @@ def test_idle_new_logger_does_not_mask_active_logger_context( assert len(workflow_a.spans) == 1 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_event_converts_to_control_span_in_batch_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -376,9 +376,9 @@ def test_agent_control_event_converts_to_control_span_in_batch_mode( assert flushed_control_span.control_id == 7 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_event_uses_empty_string_when_no_representative_input( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -401,9 +401,9 @@ def test_agent_control_event_uses_empty_string_when_no_representative_input( assert workflow.spans[0].input == "" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_event_is_dropped_when_ids_are_not_valid_uuids( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -426,9 +426,9 @@ def test_agent_control_event_is_dropped_when_ids_are_not_valid_uuids( assert workflow.spans == [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_event_streams_immediately_in_distributed_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: @@ -473,9 +473,9 @@ def test_agent_control_event_streams_immediately_in_distributed_mode( mock_traces_client_instance.ingest_spans.assert_called_with(request) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_control_span_uses_model_default_name_in_fallback_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -524,9 +524,9 @@ def force_fallback_import(name, globals=None, locals=None, fromlist=(), level=0) logger_module.LoggedControlSpan = logged_module.LoggedControlSpan -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_agent_control_event_is_dropped_when_context_does_not_match( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, fake_agent_control_modules ) -> None: diff --git a/tests/test_api_client_integration.py b/tests/test_api_client_integration.py index f10b20c1..6f408c9a 100644 --- a/tests/test_api_client_integration.py +++ b/tests/test_api_client_integration.py @@ -2,7 +2,11 @@ import pytest -from galileo.exceptions import ( +from galileo.resources import errors +from galileo.resources.api.health import healthcheck_healthcheck_get +from galileo_core.constants.request_method import RequestMethod +from galileo_core.helpers.api_client import ApiClient +from splunk_ao.exceptions import ( AuthenticationError, BadRequestError, ConflictError, @@ -11,10 +15,6 @@ RateLimitError, ServerError, ) -from galileo.resources import errors -from galileo.resources.api.health import healthcheck_healthcheck_get -from galileo_core.constants.request_method import RequestMethod -from galileo_core.helpers.api_client import ApiClient def test_common_http_errors_raise_specific_exceptions(mock_request: Callable) -> None: diff --git a/tests/test_api_headers.py b/tests/test_api_headers.py index 045ba667..1dedd354 100644 --- a/tests/test_api_headers.py +++ b/tests/test_api_headers.py @@ -2,12 +2,12 @@ from unittest.mock import patch -from galileo.project import Project -from galileo.projects import list_projects from galileo.resources.api.datasets.get_dataset_datasets_dataset_id_get import _get_kwargs as dataset_get_kwargs from galileo.resources.api.health.healthcheck_healthcheck_get import _get_kwargs as healthcheck_get_kwargs from galileo.resources.api.projects import get_all_projects_projects_all_get -from galileo.utils.headers_data import get_package_version +from splunk_ao.project import Project +from splunk_ao.projects import list_projects +from splunk_ao.utils.headers_data import get_package_version class TestApiHeaders: @@ -45,7 +45,7 @@ def test_generated_api_method_header_format(self) -> None: # Version should be a string (may be empty in test environment) assert isinstance(version_part, str) - @patch("galileo.utils.headers_data.get_package_version") + @patch("splunk_ao.utils.headers_data.get_package_version") def test_generated_api_method_with_mocked_version(self, mock_get_version) -> None: """Test header includes mocked version and method name.""" mock_get_version.return_value = "1.2.3" @@ -78,13 +78,13 @@ def capture_and_call(*args, **kwargs): with patch.object( get_all_projects_projects_all_get, "_get_kwargs", side_effect=capture_and_call ) as mock_get_kwargs: - # Test 1: galileo.project.Project.list() + # Test 1: splunk_ao.project.Project.list() try: Project.list() except Exception: pass # API call might fail in test, we only care about headers - # Test 2: galileo.projects.list_projects() + # Test 2: splunk_ao.projects.list_projects() try: list_projects() except Exception: @@ -103,8 +103,8 @@ def capture_and_call(*args, **kwargs): assert header2.startswith("galileo-python/") # But they should have different method names - assert "list@galileo.project" in header1.lower() - assert "list_projects@galileo.projects" in header2 + assert "list@splunk_ao.project" in header1.lower() + assert "list_projects@splunk_ao.projects" in header2 # Headers should be different assert header1 != header2, f"Headers should be different: '{header1}' vs '{header2}'" diff --git a/tests/test_async_base_handler.py b/tests/test_async_base_handler.py index 13d5b298..0f37fa13 100644 --- a/tests/test_async_base_handler.py +++ b/tests/test_async_base_handler.py @@ -4,16 +4,16 @@ import pytest -from galileo.handlers.base_async_handler import SplunkAOAsyncBaseHandler -from galileo.logger.logger import SplunkAOLogger +from splunk_ao.handlers.base_async_handler import SplunkAOAsyncBaseHandler +from splunk_ao.logger.logger import SplunkAOLogger from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client class TestSplunkAOAsyncBaseHandlerCallback: @pytest.fixture - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def galileo_logger(self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock): """Creates a mock Galileo logger for testing""" setup_mock_traces_client(mock_traces_client) diff --git a/tests/test_backward_compat_future.py b/tests/test_backward_compat_future.py index 718016da..cf664fc5 100644 --- a/tests/test_backward_compat_future.py +++ b/tests/test_backward_compat_future.py @@ -1,57 +1,57 @@ -"""Tests that all migrated symbols remain importable from galileo.__future__ and resolve to the same objects.""" +"""Tests that all migrated symbols remain importable from splunk_ao.__future__ and resolve to the same objects.""" def test_project_is_same_class(): - from galileo.__future__ import Project as FutureProject - from galileo.project import Project as RootProject + from splunk_ao.__future__ import Project as FutureProject + from splunk_ao.project import Project as RootProject assert FutureProject is RootProject def test_collaborator_is_same_class(): - from galileo.__future__ import Collaborator as FutureCollaborator - from galileo.collaborator import Collaborator as RootCollaborator + from splunk_ao.__future__ import Collaborator as FutureCollaborator + from splunk_ao.collaborator import Collaborator as RootCollaborator assert FutureCollaborator is RootCollaborator def test_collaborator_role_is_same_class(): - from galileo.__future__ import CollaboratorRole as FutureRole - from galileo.collaborator import CollaboratorRole as RootRole + from splunk_ao.__future__ import CollaboratorRole as FutureRole + from splunk_ao.collaborator import CollaboratorRole as RootRole assert FutureRole is RootRole def test_sync_state_is_same_class(): - from galileo.__future__.shared.base import SyncState as FutureSyncState - from galileo.shared.base import SyncState as RootSyncState + from splunk_ao.__future__.shared.base import SyncState as FutureSyncState + from splunk_ao.shared.base import SyncState as RootSyncState assert FutureSyncState is RootSyncState def test_state_management_mixin_is_same_class(): - from galileo.__future__.shared.base import StateManagementMixin as FutureMixin - from galileo.shared.base import StateManagementMixin as RootMixin + from splunk_ao.__future__.shared.base import StateManagementMixin as FutureMixin + from splunk_ao.shared.base import StateManagementMixin as RootMixin assert FutureMixin is RootMixin def test_exceptions_are_same_classes(): - from galileo.__future__.shared.exceptions import APIError as FutureAPIError - from galileo.__future__.shared.exceptions import ConfigurationError as FutureConfigError - from galileo.__future__.shared.exceptions import SplunkAOFutureError as FutureBaseError - from galileo.__future__.shared.exceptions import IntegrationNotConfiguredError as FutureIntError - from galileo.__future__.shared.exceptions import ResourceConflictError as FutureConflictError - from galileo.__future__.shared.exceptions import ResourceNotFoundError as FutureNotFoundError - from galileo.__future__.shared.exceptions import SyncError as FutureSyncError - from galileo.__future__.shared.exceptions import ValidationError as FutureValidationError - from galileo.shared.exceptions import ( + from splunk_ao.__future__.shared.exceptions import APIError as FutureAPIError + from splunk_ao.__future__.shared.exceptions import ConfigurationError as FutureConfigError + from splunk_ao.__future__.shared.exceptions import IntegrationNotConfiguredError as FutureIntError + from splunk_ao.__future__.shared.exceptions import ResourceConflictError as FutureConflictError + from splunk_ao.__future__.shared.exceptions import ResourceNotFoundError as FutureNotFoundError + from splunk_ao.__future__.shared.exceptions import SplunkAOFutureError as FutureBaseError + from splunk_ao.__future__.shared.exceptions import SyncError as FutureSyncError + from splunk_ao.__future__.shared.exceptions import ValidationError as FutureValidationError + from splunk_ao.shared.exceptions import ( APIError, ConfigurationError, - SplunkAOFutureError, IntegrationNotConfiguredError, ResourceConflictError, ResourceNotFoundError, + SplunkAOFutureError, SyncError, ValidationError, ) @@ -68,7 +68,7 @@ def test_exceptions_are_same_classes(): def test_root_init_exports(): """Test that the new exports are available from the galileo package root.""" - from galileo import Collaborator, CollaboratorRole, Project, SyncState + from splunk_ao import Collaborator, CollaboratorRole, Project, SyncState assert Project is not None assert Collaborator is not None @@ -77,47 +77,47 @@ def test_root_init_exports(): def test_configuration_is_same_class(): - from galileo.__future__.configuration import Configuration as FutureConfiguration - from galileo.configuration import Configuration as RootConfiguration + from splunk_ao.__future__.configuration import Configuration as FutureConfiguration + from splunk_ao.configuration import Configuration as RootConfiguration assert FutureConfiguration is RootConfiguration def test_model_is_same_class(): - from galileo.__future__.model import Model as FutureModel - from galileo.model import Model as RootModel + from splunk_ao.__future__.model import Model as FutureModel + from splunk_ao.model import Model as RootModel assert FutureModel is RootModel def test_dataset_is_same_class(): - from galileo.__future__.dataset import Dataset as FutureDataset - from galileo.dataset import Dataset as RootDataset + from splunk_ao.__future__.dataset import Dataset as FutureDataset + from splunk_ao.dataset import Dataset as RootDataset assert FutureDataset is RootDataset def test_prompt_is_same_class(): - from galileo.__future__.prompt import Prompt as FuturePrompt - from galileo.prompt import Prompt as RootPrompt + from splunk_ao.__future__.prompt import Prompt as FuturePrompt + from splunk_ao.prompt import Prompt as RootPrompt assert FuturePrompt is RootPrompt def test_integration_is_same_class(): - from galileo.__future__.integration import Integration as FutureIntegration - from galileo.integration import Integration as RootIntegration + from splunk_ao.__future__.integration import Integration as FutureIntegration + from splunk_ao.integration import Integration as RootIntegration assert FutureIntegration is RootIntegration def test_provider_classes_are_same(): - from galileo.__future__.provider import AnthropicProvider as FutureAnthropic - from galileo.__future__.provider import AzureProvider as FutureAzure - from galileo.__future__.provider import BedrockProvider as FutureBedrock - from galileo.__future__.provider import OpenAIProvider as FutureOpenAI - from galileo.__future__.provider import Provider as FutureProvider - from galileo.provider import AnthropicProvider, AzureProvider, BedrockProvider, OpenAIProvider, Provider + from splunk_ao.__future__.provider import AnthropicProvider as FutureAnthropic + from splunk_ao.__future__.provider import AzureProvider as FutureAzure + from splunk_ao.__future__.provider import BedrockProvider as FutureBedrock + from splunk_ao.__future__.provider import OpenAIProvider as FutureOpenAI + from splunk_ao.__future__.provider import Provider as FutureProvider + from splunk_ao.provider import AnthropicProvider, AzureProvider, BedrockProvider, OpenAIProvider, Provider assert FutureAnthropic is AnthropicProvider assert FutureAzure is AzureProvider @@ -127,12 +127,12 @@ def test_provider_classes_are_same(): def test_metric_classes_are_same(): - from galileo.__future__.metric import CodeMetric as FutureCodeMetric - from galileo.__future__.metric import SplunkAOMetric as FutureSplunkAOMetric - from galileo.__future__.metric import LlmMetric as FutureLlmMetric - from galileo.__future__.metric import LocalMetric as FutureLocalMetric - from galileo.__future__.metric import Metric as FutureMetric - from galileo.metric import CodeMetric, SplunkAOMetric, LlmMetric, LocalMetric, Metric + from splunk_ao.__future__.metric import CodeMetric as FutureCodeMetric + from splunk_ao.__future__.metric import LlmMetric as FutureLlmMetric + from splunk_ao.__future__.metric import LocalMetric as FutureLocalMetric + from splunk_ao.__future__.metric import Metric as FutureMetric + from splunk_ao.__future__.metric import SplunkAOMetric as FutureSplunkAOMetric + from splunk_ao.metric import CodeMetric, LlmMetric, LocalMetric, Metric, SplunkAOMetric assert FutureMetric is Metric assert FutureCodeMetric is CodeMetric @@ -142,25 +142,25 @@ def test_metric_classes_are_same(): def test_experiment_is_same_class(): - from galileo.__future__.experiment import Experiment as FutureExperiment - from galileo.experiment import Experiment as RootExperiment + from splunk_ao.__future__.experiment import Experiment as FutureExperiment + from splunk_ao.experiment import Experiment as RootExperiment assert FutureExperiment is RootExperiment def test_log_stream_is_same_class(): - from galileo.__future__.log_stream import LogStream as FutureLogStream - from galileo.log_stream import LogStream as RootLogStream + from splunk_ao.__future__.log_stream import LogStream as FutureLogStream + from splunk_ao.log_stream import LogStream as RootLogStream assert FutureLogStream is RootLogStream def test_shared_filter_functions_are_same(): - from galileo.__future__.shared.filter import boolean as future_boolean - from galileo.__future__.shared.filter import date as future_date - from galileo.__future__.shared.filter import number as future_number - from galileo.__future__.shared.filter import text as future_text - from galileo.shared.filter import boolean, date, number, text + from splunk_ao.__future__.shared.filter import boolean as future_boolean + from splunk_ao.__future__.shared.filter import date as future_date + from splunk_ao.__future__.shared.filter import number as future_number + from splunk_ao.__future__.shared.filter import text as future_text + from splunk_ao.shared.filter import boolean, date, number, text assert future_boolean is boolean assert future_date is date @@ -169,102 +169,102 @@ def test_shared_filter_functions_are_same(): def test_shared_sort_is_same(): - from galileo.__future__.shared.sort import sort as future_sort - from galileo.shared.sort import sort + from splunk_ao.__future__.shared.sort import sort as future_sort + from splunk_ao.shared.sort import sort assert future_sort is sort def test_shared_column_classes_are_same(): - from galileo.__future__.shared.column import Column as FutureColumn - from galileo.__future__.shared.column import ColumnCollection as FutureColumnCollection - from galileo.shared.column import Column, ColumnCollection + from splunk_ao.__future__.shared.column import Column as FutureColumn + from splunk_ao.__future__.shared.column import ColumnCollection as FutureColumnCollection + from splunk_ao.shared.column import Column, ColumnCollection assert FutureColumn is Column assert FutureColumnCollection is ColumnCollection def test_shared_query_result_is_same(): - from galileo.__future__.shared.query_result import QueryResult as FutureQueryResult - from galileo.shared.query_result import QueryResult + from splunk_ao.__future__.shared.query_result import QueryResult as FutureQueryResult + from splunk_ao.shared.query_result import QueryResult assert FutureQueryResult is QueryResult def test_shared_experiment_result_classes_are_same(): - from galileo.__future__.shared.experiment_result import ExperimentRunResult as FutureRunResult - from galileo.__future__.shared.experiment_result import ExperimentStatusInfo as FutureStatusInfo - from galileo.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo + from splunk_ao.__future__.shared.experiment_result import ExperimentRunResult as FutureRunResult + from splunk_ao.__future__.shared.experiment_result import ExperimentStatusInfo as FutureStatusInfo + from splunk_ao.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo assert FutureRunResult is ExperimentRunResult assert FutureStatusInfo is ExperimentStatusInfo def test_types_metric_spec_is_same(): - from galileo.__future__.types import MetricSpec as FutureMetricSpec - from galileo.types import MetricSpec + from splunk_ao.__future__.types import MetricSpec as FutureMetricSpec + from splunk_ao.types import MetricSpec assert FutureMetricSpec is MetricSpec def test_provider_generic_and_unconfigured_are_same(): - from galileo.__future__.provider import GenericProvider as FutureGeneric - from galileo.__future__.provider import UnconfiguredProvider as FutureUnconfigured - from galileo.provider import GenericProvider, UnconfiguredProvider + from splunk_ao.__future__.provider import GenericProvider as FutureGeneric + from splunk_ao.__future__.provider import UnconfiguredProvider as FutureUnconfigured + from splunk_ao.provider import GenericProvider, UnconfiguredProvider assert FutureGeneric is GenericProvider assert FutureUnconfigured is UnconfiguredProvider def test_metric_builtin_metrics_is_same(): - from galileo.__future__.metric import BuiltInMetrics as FutureBuiltIn - from galileo.metric import BuiltInMetrics + from splunk_ao.__future__.metric import BuiltInMetrics as FutureBuiltIn + from splunk_ao.metric import BuiltInMetrics assert FutureBuiltIn is BuiltInMetrics def test_prompt_private_symbols_are_same(): - from galileo.__future__.prompt import PromptVersion as FuturePromptVersion - from galileo.__future__.prompt import _parse_template_to_messages as future_parse - from galileo.prompt import PromptVersion, _parse_template_to_messages + from splunk_ao.__future__.prompt import PromptVersion as FuturePromptVersion + from splunk_ao.__future__.prompt import _parse_template_to_messages as future_parse + from splunk_ao.prompt import PromptVersion, _parse_template_to_messages assert FuturePromptVersion is PromptVersion assert future_parse is _parse_template_to_messages def test_shared_column_unwrap_unset_is_same(): - from galileo.__future__.shared.column import _unwrap_unset as future_unwrap - from galileo.shared.column import _unwrap_unset + from splunk_ao.__future__.shared.column import _unwrap_unset as future_unwrap + from splunk_ao.shared.column import _unwrap_unset assert future_unwrap is _unwrap_unset def test_shared_query_result_flatten_dict_is_same(): - from galileo.__future__.shared.query_result import _flatten_dict as future_flatten - from galileo.shared.query_result import _flatten_dict + from splunk_ao.__future__.shared.query_result import _flatten_dict as future_flatten + from splunk_ao.shared.query_result import _flatten_dict assert future_flatten is _flatten_dict def test_shared_experiment_result_phase_info_is_same(): - from galileo.__future__.shared.experiment_result import ExperimentPhaseInfo as FuturePhaseInfo - from galileo.shared.experiment_result import ExperimentPhaseInfo + from splunk_ao.__future__.shared.experiment_result import ExperimentPhaseInfo as FuturePhaseInfo + from splunk_ao.shared.experiment_result import ExperimentPhaseInfo assert FuturePhaseInfo is ExperimentPhaseInfo def test_shared_utils_classproperty_is_same(): - from galileo.__future__.shared.utils import classproperty as future_classproperty - from galileo.shared.utils import classproperty + from splunk_ao.__future__.shared.utils import classproperty as future_classproperty + from splunk_ao.shared.utils import classproperty assert future_classproperty is classproperty def test_configuration_private_symbols_are_same(): - from galileo.__future__.configuration import _CONFIGURATION_KEYS as future_keys - from galileo.__future__.configuration import VALID_LOG_LEVELS as future_levels - from galileo.__future__.configuration import parse_log_level as future_parse - from galileo.configuration import _CONFIGURATION_KEYS, VALID_LOG_LEVELS, parse_log_level + from splunk_ao.__future__.configuration import _CONFIGURATION_KEYS as future_keys + from splunk_ao.__future__.configuration import VALID_LOG_LEVELS as future_levels + from splunk_ao.__future__.configuration import parse_log_level as future_parse + from splunk_ao.configuration import _CONFIGURATION_KEYS, VALID_LOG_LEVELS, parse_log_level assert future_keys is _CONFIGURATION_KEYS assert future_levels is VALID_LOG_LEVELS @@ -272,15 +272,15 @@ def test_configuration_private_symbols_are_same(): def test_shared_sort_class_is_same(): - from galileo.__future__.shared.sort import Sort as FutureSort - from galileo.shared.sort import Sort + from splunk_ao.__future__.shared.sort import Sort as FutureSort + from splunk_ao.shared.sort import Sort assert FutureSort is Sort def test_root_init_has_new_exports(): - """Test that all newly migrated domain objects are available from galileo package root.""" - from galileo import ( + """Test that all newly migrated domain objects are available from splunk_ao package root.""" + from splunk_ao import ( AnthropicProvider, AzureProvider, BedrockProvider, @@ -288,7 +288,6 @@ def test_root_init_has_new_exports(): Configuration, Dataset, Experiment, - SplunkAOMetric, Integration, LlmMetric, LocalMetric, @@ -299,6 +298,7 @@ def test_root_init_has_new_exports(): OpenAIProvider, Prompt, Provider, + SplunkAOMetric, ) assert Configuration is not None diff --git a/tests/test_base_handler.py b/tests/test_base_handler.py index 08caaaeb..56cc54d9 100644 --- a/tests/test_base_handler.py +++ b/tests/test_base_handler.py @@ -4,16 +4,16 @@ import pytest -from galileo.handlers.base_handler import SplunkAOBaseHandler -from galileo.logger.logger import SplunkAOLogger +from splunk_ao.handlers.base_handler import SplunkAOBaseHandler +from splunk_ao.logger.logger import SplunkAOLogger from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client class TestSplunkAOBaseHandler: @pytest.fixture - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def galileo_logger(self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock): """Creates a mock Galileo logger for testing""" setup_mock_traces_client(mock_traces_client) diff --git a/tests/test_column.py b/tests/test_column.py index 607bb107..e09b11de 100644 --- a/tests/test_column.py +++ b/tests/test_column.py @@ -20,8 +20,8 @@ ) from galileo.resources.models.column_info import ColumnInfo from galileo.resources.types import UNSET -from galileo.shared.column import Column, ColumnCollection, _unwrap_unset -from galileo.shared.exceptions import ValidationError +from splunk_ao.shared.column import Column, ColumnCollection, _unwrap_unset +from splunk_ao.shared.exceptions import ValidationError def _create_mock_column_info( diff --git a/tests/test_config.py b/tests/test_config.py index cb16b185..242fe7a9 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -2,8 +2,8 @@ import pytest -from galileo.config import SplunkAOConfig -from galileo.shared.exceptions import ConfigurationError +from splunk_ao.config import SplunkAOConfig +from splunk_ao.shared.exceptions import ConfigurationError # Auth env vars cleared in tests that exercise the missing-auth guard. _AUTH_ENV_VARS = ( diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 62b32466..0e567bdd 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -6,9 +6,9 @@ import pytest -from galileo.config import SplunkAOConfig -from galileo.configuration import _CONFIGURATION_KEYS, VALID_LOG_LEVELS, Configuration, parse_log_level -from galileo.shared.exceptions import ConfigurationError +from splunk_ao.config import SplunkAOConfig +from splunk_ao.configuration import _CONFIGURATION_KEYS, VALID_LOG_LEVELS, Configuration, parse_log_level +from splunk_ao.shared.exceptions import ConfigurationError class TestParseLogLevel: @@ -335,7 +335,7 @@ def test_connect_fails_without_api_key( ("generic", "Unknown error", "Configuration validation failed"), ], ) - @patch("galileo.configuration.SplunkAOConfig.get") + @patch("splunk_ao.configuration.SplunkAOConfig.get") def test_connect_handles_different_error_types( self, mock_config_get: Mock, diff --git a/tests/test_crewai_handler.py b/tests/test_crewai_handler.py index 0c5775e8..6c37f39e 100644 --- a/tests/test_crewai_handler.py +++ b/tests/test_crewai_handler.py @@ -9,8 +9,8 @@ # Skip all tests in this module on Python 3.14+ (crewai doesn't support it yet) pytestmark = pytest.mark.skipif(sys.version_info >= (3, 14), reason="crewai does not support Python 3.14+") -from galileo.handlers.crewai.handler import CrewAIEventListener # noqa: E402 -from galileo.schema.handlers import NodeType # noqa: E402 +from splunk_ao.handlers.crewai.handler import CrewAIEventListener # noqa: E402 +from splunk_ao.schema.handlers import NodeType # noqa: E402 from tests.testutils.setup import ( # noqa: E402 setup_mock_logstreams_client, setup_mock_projects_client, @@ -80,15 +80,15 @@ def __init__(self, raw="Test output"): def mock_galileo_logger(): """Creates a mock Galileo logger for testing.""" with ( - patch("galileo.logger.logger.LogStreams") as mock_logstreams, - patch("galileo.logger.logger.Projects") as mock_projects, - patch("galileo.logger.logger.Traces") as mock_traces_client, + patch("splunk_ao.logger.logger.LogStreams") as mock_logstreams, + patch("splunk_ao.logger.logger.Projects") as mock_projects, + patch("splunk_ao.logger.logger.Traces") as mock_traces_client, ): setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects) setup_mock_logstreams_client(mock_logstreams) - from galileo.logger.logger import SplunkAOLogger + from splunk_ao.logger.logger import SplunkAOLogger return SplunkAOLogger(project="test_project", log_stream="test_log_stream") @@ -97,11 +97,11 @@ def mock_galileo_logger(): def crewai_callback(mock_galileo_logger): """Creates a CrewAIEventListener instance for testing.""" with ( - patch("galileo.handlers.crewai.handler._crewai_imports_resolved", True), - patch("galileo.handlers.crewai.handler.CREWAI_AVAILABLE", False), - patch("galileo.handlers.crewai.handler.LITE_LLM_AVAILABLE", False), + patch("splunk_ao.handlers.crewai.handler._crewai_imports_resolved", True), + patch("splunk_ao.handlers.crewai.handler.CREWAI_AVAILABLE", False), + patch("splunk_ao.handlers.crewai.handler.LITE_LLM_AVAILABLE", False), ): - from galileo.handlers.crewai.handler import CrewAIEventListener + from splunk_ao.handlers.crewai.handler import CrewAIEventListener return CrewAIEventListener( galileo_logger=mock_galileo_logger, start_new_trace=True, flush_on_crew_completed=False @@ -111,11 +111,11 @@ def crewai_callback(mock_galileo_logger): def test_initialization_with_crewai_available(mock_galileo_logger) -> None: """Test CrewAIEventListener initialization when CrewAI is available.""" with ( - patch("galileo.handlers.crewai.handler._crewai_imports_resolved", True), - patch("galileo.handlers.crewai.handler.CREWAI_AVAILABLE", True), - patch("galileo.handlers.crewai.handler.LITE_LLM_AVAILABLE", True), + patch("splunk_ao.handlers.crewai.handler._crewai_imports_resolved", True), + patch("splunk_ao.handlers.crewai.handler.CREWAI_AVAILABLE", True), + patch("splunk_ao.handlers.crewai.handler.LITE_LLM_AVAILABLE", True), ): - from galileo.handlers.crewai.handler import CrewAIEventListener + from splunk_ao.handlers.crewai.handler import CrewAIEventListener callback = CrewAIEventListener( galileo_logger=mock_galileo_logger, start_new_trace=False, flush_on_crew_completed=True @@ -129,11 +129,11 @@ def test_initialization_with_crewai_available(mock_galileo_logger) -> None: def test_initialization_with_crewai_unavailable(mock_galileo_logger) -> None: """Test CrewAIEventListener initialization when CrewAI is unavailable.""" with ( - patch("galileo.handlers.crewai.handler._crewai_imports_resolved", True), - patch("galileo.handlers.crewai.handler.CREWAI_AVAILABLE", False), - patch("galileo.handlers.crewai.handler.LITE_LLM_AVAILABLE", False), + patch("splunk_ao.handlers.crewai.handler._crewai_imports_resolved", True), + patch("splunk_ao.handlers.crewai.handler.CREWAI_AVAILABLE", False), + patch("splunk_ao.handlers.crewai.handler.LITE_LLM_AVAILABLE", False), ): - from galileo.handlers.crewai.handler import CrewAIEventListener + from splunk_ao.handlers.crewai.handler import CrewAIEventListener callback = CrewAIEventListener(galileo_logger=mock_galileo_logger) @@ -644,7 +644,7 @@ def test_setup_listeners_crewai_unavailable(crewai_callback: CrewAIEventListener """Test setup_listeners when CrewAI is unavailable.""" mock_event_bus = Mock() - with patch("galileo.handlers.crewai.handler.CREWAI_AVAILABLE", False): + with patch("splunk_ao.handlers.crewai.handler.CREWAI_AVAILABLE", False): crewai_callback.setup_listeners(mock_event_bus) # Verify that no event listeners were registered diff --git a/tests/test_dataset.py b/tests/test_dataset.py index 01a81826..e2025339 100644 --- a/tests/test_dataset.py +++ b/tests/test_dataset.py @@ -3,13 +3,13 @@ import pytest -from galileo.dataset import Dataset, DatasetVersionContent from galileo.resources.models.dataset_row import DatasetRow from galileo.resources.models.dataset_row_values_dict import DatasetRowValuesDict from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.list_dataset_version_response import ListDatasetVersionResponse -from galileo.shared.base import SyncState -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError +from splunk_ao.dataset import Dataset, DatasetVersionContent +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError class TestDatasetInitialization: @@ -40,7 +40,7 @@ def test_init_without_name_raises_validation_error(self, reset_configuration: No class TestDatasetCreate: """Test suite for Dataset.create() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_create_persists_dataset_to_api( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -56,7 +56,7 @@ def test_create_persists_dataset_to_api( assert dataset.id == mock_dataset.id assert dataset.is_synced() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_create_handles_api_failure(self, mock_datasets_class: MagicMock, reset_configuration: None) -> None: """Test create() handles API failures and sets state correctly.""" mock_service = MagicMock() @@ -75,7 +75,7 @@ class TestDatasetGet: """Test suite for Dataset.get() class method.""" @pytest.mark.parametrize("lookup_key", ["name", "id"]) - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_returns_dataset( self, mock_datasets_class: MagicMock, lookup_key: str, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -90,7 +90,7 @@ def test_get_returns_dataset( assert dataset is not None assert dataset.is_synced() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_returns_none_when_not_found(self, mock_datasets_class: MagicMock, reset_configuration: None) -> None: """Test get() returns None when dataset is not found.""" mock_service = MagicMock() @@ -101,7 +101,7 @@ def test_get_returns_none_when_not_found(self, mock_datasets_class: MagicMock, r assert dataset is None - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_raises_error_without_id_or_name( self, mock_datasets_class: MagicMock, reset_configuration: None ) -> None: @@ -113,7 +113,7 @@ def test_get_raises_error_without_id_or_name( class TestDatasetList: """Test suite for Dataset.list() class method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_list_returns_all_datasets(self, mock_datasets_class: MagicMock, reset_configuration: None) -> None: """Test list() returns a list of synced dataset instances.""" mock_service = MagicMock() @@ -143,7 +143,7 @@ def test_list_returns_all_datasets(self, mock_datasets_class: MagicMock, reset_c class TestDatasetContent: """Test suite for dataset content management.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_content( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -177,7 +177,7 @@ def test_content_methods_raise_error_for_local_only(self, method_name: str, rese else: getattr(dataset, method_name)() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_add_rows(self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock) -> None: """Test add_rows() adds rows to the dataset.""" mock_service = MagicMock() @@ -193,7 +193,7 @@ def test_add_rows(self, mock_datasets_class: MagicMock, reset_configuration: Non assert result == dataset # Verify method chaining assert dataset.is_synced() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_extend_generates_rows_and_adds_to_dataset( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -238,7 +238,7 @@ def make_row(values_dict: dict) -> DatasetRow: # Then: the generated DatasetRow objects are returned assert result == generated_rows - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_extend_with_empty_result_skips_add_rows( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -262,7 +262,7 @@ def test_extend_with_empty_result_skips_add_rows( class TestDatasetDelete: """Test suite for Dataset.delete() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_delete_removes_dataset( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -288,7 +288,7 @@ def test_delete_raises_error_for_local_only(self, reset_configuration: None) -> class TestDatasetRefresh: """Test suite for Dataset.refresh() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_refresh_updates_attributes(self, mock_datasets_class: MagicMock, reset_configuration: None) -> None: """Test refresh() updates all attributes from the API.""" mock_service = MagicMock() @@ -334,7 +334,7 @@ def test_refresh_raises_error_for_local_only(self, reset_configuration: None) -> class TestDatasetSave: """Test suite for Dataset.save() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_save_local_only_delegates_to_create( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -352,7 +352,7 @@ def test_save_local_only_delegates_to_create( assert result.id == mock_dataset.id assert result.is_synced() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_save_synced_is_noop( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -391,7 +391,7 @@ def test_save_without_id_raises_value_error(self, reset_configuration: None) -> with pytest.raises(ValueError, match="Dataset ID is not set"): dataset.save() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_save_dirty_calls_update_and_syncs_attributes( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -430,7 +430,7 @@ def test_save_dirty_calls_update_and_syncs_attributes( assert result.id == mock_dataset.id assert result.is_synced() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_save_failed_sync_raises_value_error( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -446,7 +446,7 @@ def test_save_failed_sync_raises_value_error( with pytest.raises(ValueError, match="FAILED_SYNC"): dataset.save() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_save_handles_api_failure( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -482,7 +482,7 @@ def test_str_and_repr(self, reset_configuration: None) -> None: class TestDatasetGetVersions: """Test suite for Dataset.get_versions() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_versions_returns_response( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -503,7 +503,7 @@ def test_get_versions_returns_response( assert result == mock_versions mock_dataset.get_version_history.assert_called_once() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_versions_raises_when_dataset_not_found( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -519,7 +519,7 @@ def test_get_versions_raises_when_dataset_not_found( with pytest.raises(ResourceNotFoundError, match="not found"): dataset.get_versions() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_versions_raises_on_http_validation_error( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -536,7 +536,7 @@ def test_get_versions_raises_on_http_validation_error( with pytest.raises(ValueError, match="Failed to retrieve dataset versions"): dataset.get_versions() - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_versions_raises_on_none_response( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -557,7 +557,7 @@ def test_get_versions_raises_on_none_response( class TestDatasetGetVersionContent: """Test suite for Dataset.get_version_content() method.""" - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_version_content_returns_content( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -578,7 +578,7 @@ def test_get_version_content_returns_content( assert result == mock_content mock_dataset.load_version.assert_called_once_with(1) - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_version_content_raises_when_dataset_not_found( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -594,7 +594,7 @@ def test_get_version_content_raises_when_dataset_not_found( with pytest.raises(ResourceNotFoundError, match="not found"): dataset.get_version_content(index=1) - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_version_content_raises_on_http_validation_error( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: @@ -611,7 +611,7 @@ def test_get_version_content_raises_on_http_validation_error( with pytest.raises(ValueError, match="Failed to retrieve version content"): dataset.get_version_content(index=1) - @patch("galileo.dataset.Datasets") + @patch("splunk_ao.dataset.Datasets") def test_get_version_content_raises_on_none_response( self, mock_datasets_class: MagicMock, reset_configuration: None, mock_dataset: MagicMock ) -> None: diff --git a/tests/test_datasets.py b/tests/test_datasets.py index e989b677..cf6f11bb 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -5,21 +5,6 @@ import pytest -from galileo.datasets import ( - DEFAULT_EXTEND_MODEL_ALIAS, - Dataset, - DatasetAPIException, - DatasetAppendRow, - DatasetAppendRowValues, - Datasets, - UpdateDatasetContentRequest, - convert_dataset_row_to_record, - create_dataset, - extend_dataset, - get_dataset_version, - get_dataset_version_history, - list_dataset_projects, -) from galileo.resources.models import ( BodyCreateDatasetDatasetsPost, DatasetContent, @@ -39,7 +24,22 @@ from galileo.resources.models.dataset_row_values_dict import DatasetRowValuesDict from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.types import UNSET, Response -from galileo.schema.datasets import DatasetRecord +from splunk_ao.datasets import ( + DEFAULT_EXTEND_MODEL_ALIAS, + Dataset, + DatasetAPIException, + DatasetAppendRow, + DatasetAppendRowValues, + Datasets, + UpdateDatasetContentRequest, + convert_dataset_row_to_record, + create_dataset, + extend_dataset, + get_dataset_version, + get_dataset_version_history, + list_dataset_projects, +) +from splunk_ao.schema.datasets import DatasetRecord def dataset_content(): @@ -154,14 +154,14 @@ def list_dataset_versions(): ) -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_validation_error(create_dataset_datasets_post_mock: Mock) -> None: with pytest.raises(ValueError) as exc_info: create_dataset(name="my_dataset_name", content=None) assert "Invalid dataset type: ''." in str(exc_info.value), str(exc_info) -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_with_empty_list(create_dataset_datasets_post_mock: Mock) -> None: create_dataset_datasets_post_mock.sync_detailed.return_value = Response( content=b'{"id":"bb830fae-99d3-4ce7-bef9-300d528e0060","permissions":[],"name":"my_dataset_name","created_at":"2025-05-16T16:26:41.76451","email":"user.test@galileo.ai","first_name":"","last_name":""},"current_version_index":1,"draft":false}', @@ -192,7 +192,7 @@ def test_create_dataset_with_empty_list(create_dataset_datasets_post_mock: Mock) ) -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_with_empty_dict(create_dataset_datasets_post_mock: Mock) -> None: create_dataset_datasets_post_mock.sync_detailed.return_value = Response( content=b'{"id":"bb830fae-99d3-4ce7-bef9-300d528e0060","permissions":[],"name":"my_dataset_name","created_at":"2025-05-16T16:26:41.76451","email":"user.test@galileo.ai","first_name":"","last_name":""},"current_version_index":1,"draft":false}', @@ -223,8 +223,8 @@ def test_create_dataset_with_empty_dict(create_dataset_datasets_post_mock: Mock) ) -@patch("galileo.datasets.get_dataset_version_content_datasets_dataset_id_versions_version_index_content_get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.datasets.get_dataset_version_content_datasets_dataset_id_versions_version_index_content_get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") def test_get_dataset_version_using_dataset_id( get_dataset_datasets_dataset_id_get: Mock, get_dataset_version_mock: Mock ) -> None: @@ -242,8 +242,8 @@ def test_get_dataset_version_using_dataset_id( ) -@patch("galileo.datasets.get_dataset_version_content_datasets_dataset_id_versions_version_index_content_get") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.datasets.get_dataset_version_content_datasets_dataset_id_versions_version_index_content_get") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") def test_get_dataset_version_using_dataset_name( query_datasets_datasets_query_post: Mock, get_dataset_version_mock: Mock ) -> None: @@ -268,8 +268,8 @@ def test_get_dataset_version_wo_dataset_name_or_dataset_id() -> None: assert "Either dataset_name or dataset_id must be provided." in str(exc_info.value), str(exc_info) -@patch("galileo.datasets.query_dataset_versions_datasets_dataset_id_versions_query_post") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.datasets.query_dataset_versions_datasets_dataset_id_versions_query_post") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") def test_get_dataset_version_history_using_dataset_id( get_dataset_datasets_dataset_id_get: Mock, get_dataset_versions_mock: Mock ) -> None: @@ -288,8 +288,8 @@ def test_get_dataset_version_history_using_dataset_id( ) -@patch("galileo.datasets.query_dataset_versions_datasets_dataset_id_versions_query_post") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.datasets.query_dataset_versions_datasets_dataset_id_versions_query_post") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") def test_get_dataset_version_history_using_dataset_name( query_datasets_datasets_query_post: Mock, get_dataset_version_mock: Mock ) -> None: @@ -425,7 +425,7 @@ def test_convert_dataset_row_to_record() -> None: assert record.ground_truth == "4" # Property reflects output value -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test__get_etag(get_dataset_content_by_id_patch: Mock) -> None: dataset = Dataset(dataset_db=dataset_db()) @@ -440,9 +440,9 @@ def test__get_etag(get_dataset_content_by_id_patch: Mock) -> None: ) -@patch("galileo.datasets.Dataset._get_etag", return_value="test_etag") -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.update_dataset_content_datasets_dataset_id_content_patch") +@patch("splunk_ao.datasets.Dataset._get_etag", return_value="test_etag") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.update_dataset_content_datasets_dataset_id_content_patch") def test_dataset_add_rows_success( update_dataset_patch: Mock, get_dataset_content_patch: Mock, etag_patch: Mock ) -> None: @@ -471,9 +471,9 @@ def test_dataset_add_rows_success( get_dataset_content_patch.sync.assert_called_once() -@patch("galileo.datasets.Dataset._get_etag", return_value="test_etag") -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.update_dataset_content_datasets_dataset_id_content_patch") +@patch("splunk_ao.datasets.Dataset._get_etag", return_value="test_etag") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.update_dataset_content_datasets_dataset_id_content_patch") def test_dataset_add_rows_failure( update_dataset_patch: Mock, get_dataset_content_patch: Mock, etag_patch: Mock ) -> None: @@ -520,10 +520,10 @@ def test_get_dataset_validation_errors() -> None: assert str(exc_info.value) == "Exactly one of 'id' or 'name' must be provided" -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") -@patch("galileo.datasets.time.sleep") # Mock sleep to avoid actual delays +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.time.sleep") # Mock sleep to avoid actual delays def test_extend_dataset_success( sleep_mock: Mock, extend_dataset_mock: Mock, get_extend_status_mock: Mock, get_dataset_content_mock: Mock ) -> None: @@ -577,7 +577,7 @@ def test_extend_dataset_success( assert sleep_mock.call_count == 2 # Called 2 times (between the 3 status checks) -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") def test_extend_dataset_uses_default_model_alias_when_prompt_settings_is_none(extend_dataset_mock: Mock) -> None: # Given: no prompt_settings provided extend_dataset_mock.sync.return_value = HTTPValidationError() @@ -591,7 +591,7 @@ def test_extend_dataset_uses_default_model_alias_when_prompt_settings_is_none(ex assert call_body.prompt_settings.model_alias == DEFAULT_EXTEND_MODEL_ALIAS -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") def test_extend_dataset_uses_default_model_alias_when_model_alias_key_missing(extend_dataset_mock: Mock) -> None: # Given: prompt_settings provided but without a "model_alias" key extend_dataset_mock.sync.return_value = HTTPValidationError() @@ -605,7 +605,7 @@ def test_extend_dataset_uses_default_model_alias_when_model_alias_key_missing(ex assert call_body.prompt_settings.model_alias == DEFAULT_EXTEND_MODEL_ALIAS -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") def test_extend_dataset_preserves_non_model_alias_prompt_settings(extend_dataset_mock: Mock) -> None: """Regression for sc-61766: extend_dataset must forward all prompt_settings fields, not just model_alias.""" @@ -628,7 +628,7 @@ def test_extend_dataset_preserves_non_model_alias_prompt_settings(extend_dataset assert call_body.prompt_settings.top_p == 0.9 -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") def test_extend_dataset_does_not_mutate_caller_prompt_settings(extend_dataset_mock: Mock) -> None: """extend_dataset must not mutate the caller's prompt_settings dict (e.g. inject model_alias).""" # Given: a caller dict without model_alias @@ -643,7 +643,7 @@ def test_extend_dataset_does_not_mutate_caller_prompt_settings(extend_dataset_mo assert caller_settings == {"temperature": 0.5} -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") def test_extend_dataset_api_failure(extend_dataset_mock: Mock) -> None: """Test extend_dataset when the initial API call fails.""" @@ -655,10 +655,10 @@ def test_extend_dataset_api_failure(extend_dataset_mock: Mock) -> None: extend_dataset(prompt_settings={"model_alias": "GPT-4o mini"}, prompt="Test prompt", count=1) -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") -@patch("galileo.datasets.time.sleep") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.time.sleep") def test_extend_dataset_unexpected_error_in_progress_message( sleep_mock: Mock, extend_dataset_mock: Mock, get_extend_status_mock: Mock, get_dataset_content_mock: Mock ) -> None: @@ -679,10 +679,10 @@ def test_extend_dataset_unexpected_error_in_progress_message( get_dataset_content_mock.sync.assert_not_called() -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") -@patch("galileo.datasets.time.sleep") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.time.sleep") def test_extend_dataset_unexpected_error_case_insensitive( sleep_mock: Mock, extend_dataset_mock: Mock, get_extend_status_mock: Mock, get_dataset_content_mock: Mock ) -> None: @@ -703,15 +703,15 @@ def test_extend_dataset_unexpected_error_case_insensitive( get_dataset_content_mock.sync.assert_not_called() -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") -@patch("galileo.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") -@patch("galileo.datasets.extend_dataset_content_datasets_extend_post") -@patch("galileo.datasets.time.sleep") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_synthetic_extend_status_datasets_extend_dataset_id_get") +@patch("splunk_ao.datasets.extend_dataset_content_datasets_extend_post") +@patch("splunk_ao.datasets.time.sleep") def test_dataset_generate_propagates_unexpected_error( sleep_mock: Mock, extend_dataset_mock: Mock, get_extend_status_mock: Mock, get_dataset_content_mock: Mock ) -> None: """Test that Dataset.generate propagates DatasetAPIException from extend when a job fails.""" - from galileo.dataset import Dataset as FutureDataset + from splunk_ao.dataset import Dataset as FutureDataset # Given: the underlying extend job signals failure via progress_message extended_dataset_id = "abc-123" @@ -734,11 +734,11 @@ def test_dataset_generate_propagates_unexpected_error( # =================================================================== -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") def test_list_datasets_with_project_id(query_datasets_mock: Mock, get_project_mock: Mock) -> None: """Test listing datasets filtered by project_id.""" - from galileo.datasets import list_datasets + from splunk_ao.datasets import list_datasets project_id = "test-project-id" dataset_db = DatasetDB( @@ -776,11 +776,11 @@ def test_list_datasets_with_project_id(query_datasets_mock: Mock, get_project_mo assert call_args.kwargs["body"].filters[0].value == project_id -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") def test_list_datasets_with_project_name(query_datasets_mock: Mock, get_project_mock: Mock) -> None: """Test listing datasets filtered by project_name.""" - from galileo.datasets import list_datasets + from splunk_ao.datasets import list_datasets project_name = "Test Project" project_id = "test-project-id" @@ -820,16 +820,16 @@ def test_list_datasets_with_project_name(query_datasets_mock: Mock, get_project_ def test_list_datasets_with_both_project_params() -> None: """Test that providing both project_id and project_name raises an error.""" - from galileo.datasets import list_datasets + from splunk_ao.datasets import list_datasets with pytest.raises(ValueError, match="Only one of 'project_id' or 'project_name' can be provided, not both"): list_datasets(project_id="id-123", project_name="My Project") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.projects.Projects.get") def test_list_datasets_with_nonexistent_project_name(get_project_mock: Mock) -> None: """Test listing datasets with a project name that doesn't exist.""" - from galileo.datasets import list_datasets + from splunk_ao.datasets import list_datasets # Mock project not found get_project_mock.return_value = None @@ -838,13 +838,13 @@ def test_list_datasets_with_nonexistent_project_name(get_project_mock: Mock) -> list_datasets(project_name="Nonexistent Project") -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_get_dataset_with_project_id(list_projects_mock: Mock, get_dataset_mock: Mock, get_project_mock: Mock) -> None: """Test getting a dataset with project_id validation.""" - from galileo.datasets import get_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import get_dataset dataset_id = "dataset-1" project_id = "test-project-id" @@ -885,15 +885,15 @@ def test_get_dataset_with_project_id(list_projects_mock: Mock, get_dataset_mock: list_projects_mock.assert_called_once() -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_get_dataset_with_project_name( list_projects_mock: Mock, query_datasets_mock: Mock, get_project_mock: Mock ) -> None: """Test getting a dataset with project_name validation.""" - from galileo.datasets import get_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import get_dataset dataset_name = "Test Dataset" dataset_id = "dataset-1" @@ -938,17 +938,17 @@ def test_get_dataset_with_project_name( def test_get_dataset_with_both_project_params() -> None: """Test that providing both project_id and project_name raises an error.""" - from galileo.datasets import get_dataset + from splunk_ao.datasets import get_dataset with pytest.raises(ValueError, match="Only one of 'project_id' or 'project_name' can be provided, not both"): get_dataset(name="my-dataset", project_id="id-123", project_name="My Project") -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") def test_get_dataset_with_nonexistent_project(get_dataset_mock: Mock, get_project_mock: Mock) -> None: """Test getting a dataset with a project that doesn't exist.""" - from galileo.datasets import get_dataset + from splunk_ao.datasets import get_dataset dataset_id = "dataset-1" @@ -974,13 +974,13 @@ def test_get_dataset_with_nonexistent_project(get_dataset_mock: Mock, get_projec get_dataset(id=dataset_id, project_id="nonexistent-project") -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_get_dataset_not_in_project(list_projects_mock: Mock, get_dataset_mock: Mock, get_project_mock: Mock) -> None: """Test getting a dataset that is not used in the specified project.""" - from galileo.datasets import get_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import get_dataset dataset_id = "dataset-1" project_id = "test-project-id" @@ -1015,16 +1015,16 @@ def test_get_dataset_not_in_project(list_projects_mock: Mock, get_dataset_mock: get_dataset(id=dataset_id, project_id=project_id) -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") -@patch("galileo.datasets.delete_dataset_datasets_dataset_id_delete") +@patch("splunk_ao.datasets.delete_dataset_datasets_dataset_id_delete") def test_delete_dataset_with_project_id( delete_dataset_mock: Mock, list_projects_mock: Mock, get_dataset_mock: Mock, get_project_mock: Mock ) -> None: """Test deleting a dataset with project_id validation.""" - from galileo.datasets import delete_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import delete_dataset dataset_id = "dataset-1" project_id = "test-project-id" @@ -1064,16 +1064,16 @@ def test_delete_dataset_with_project_id( delete_dataset_mock.sync.assert_called_once_with(client=ANY, dataset_id=dataset_id) -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") -@patch("galileo.datasets.delete_dataset_datasets_dataset_id_delete") +@patch("splunk_ao.datasets.delete_dataset_datasets_dataset_id_delete") def test_delete_dataset_with_project_name( delete_dataset_mock: Mock, list_projects_mock: Mock, query_datasets_mock: Mock, get_project_mock: Mock ) -> None: """Test deleting a dataset with project_name validation.""" - from galileo.datasets import delete_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import delete_dataset dataset_name = "Test Dataset" dataset_id = "dataset-1" @@ -1117,21 +1117,21 @@ def test_delete_dataset_with_project_name( def test_delete_dataset_with_both_project_params() -> None: """Test that providing both project_id and project_name raises an error.""" - from galileo.datasets import delete_dataset + from splunk_ao.datasets import delete_dataset with pytest.raises(ValueError, match="Only one of 'project_id' or 'project_name' can be provided, not both"): delete_dataset(name="my-dataset", project_id="id-123", project_name="My Project") -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_delete_dataset_not_in_project( list_projects_mock: Mock, get_dataset_mock: Mock, get_project_mock: Mock ) -> None: """Test deleting a dataset that is not used in the specified project.""" - from galileo.datasets import delete_dataset from galileo.resources.models import ListDatasetProjectsResponse + from splunk_ao.datasets import delete_dataset dataset_id = "dataset-1" project_id = "test-project-id" @@ -1166,11 +1166,11 @@ def test_delete_dataset_not_in_project( delete_dataset(id=dataset_id, project_id=project_id) -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_with_project_id(create_dataset_mock: Mock, get_project_mock: Mock) -> None: """Test creating a dataset with project_id association.""" - from galileo.datasets import create_dataset + from splunk_ao.datasets import create_dataset project_id = "test-project-id" dataset_name = "Test Dataset" @@ -1211,11 +1211,11 @@ def test_create_dataset_with_project_id(create_dataset_mock: Mock, get_project_m assert call_args.kwargs["body"].project_id == project_id -@patch("galileo.projects.Projects.get") -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.projects.Projects.get") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_with_project_name(create_dataset_mock: Mock, get_project_mock: Mock) -> None: """Test creating a dataset with project_name association.""" - from galileo.datasets import create_dataset + from splunk_ao.datasets import create_dataset project_name = "Test Project" project_id = "test-project-id" @@ -1264,16 +1264,16 @@ def test_create_dataset_with_project_name(create_dataset_mock: Mock, get_project def test_create_dataset_with_both_project_params() -> None: """Test that providing both project_id and project_name raises an error.""" - from galileo.datasets import create_dataset + from splunk_ao.datasets import create_dataset with pytest.raises(ValueError, match="Only one of 'project_id' or 'project_name' can be provided, not both"): create_dataset(name="test-dataset", content=[{"input": "test"}], project_id="id-123", project_name="My Project") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.projects.Projects.get") def test_create_dataset_with_nonexistent_project(get_project_mock: Mock) -> None: """Test creating a dataset with a project that doesn't exist.""" - from galileo.datasets import create_dataset + from splunk_ao.datasets import create_dataset # Mock project retrieval - return None to simulate nonexistent project get_project_mock.return_value = None @@ -1282,14 +1282,14 @@ def test_create_dataset_with_nonexistent_project(get_project_mock: Mock) -> None create_dataset(name="test-dataset", content=[{"input": "test"}], project_id="nonexistent-project") -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_without_project_uses_unset(create_dataset_mock: Mock) -> None: """Test that creating a dataset without project_id uses UNSET, not None. This prevents the string 'None' from being sent to the API which would cause a 422 validation error. """ - from galileo.datasets import create_dataset + from splunk_ao.datasets import create_dataset # Mock successful dataset creation create_dataset_mock.sync_detailed.return_value = Response( @@ -1386,7 +1386,7 @@ def test_dataset_list_projects(list_projects_mock: Mock) -> None: list_projects_mock.assert_called_once_with(dataset_id="dataset-1", client=ANY, limit=100) -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_list_dataset_projects_by_id(list_projects_mock: Mock, get_dataset_mock: Mock) -> None: """Test list_dataset_projects() convenience function with dataset_id.""" @@ -1431,7 +1431,7 @@ def test_list_dataset_projects_by_id(list_projects_mock: Mock, get_dataset_mock: get_dataset_mock.sync.assert_called_once_with(client=ANY, dataset_id=dataset_id) -@patch("galileo.datasets.query_datasets_datasets_query_post") +@patch("splunk_ao.datasets.query_datasets_datasets_query_post") @patch("galileo.resources.api.datasets.list_dataset_projects_datasets_dataset_id_projects_get.sync") def test_list_dataset_projects_by_name(list_projects_mock: Mock, query_datasets_mock: Mock) -> None: """Test list_dataset_projects() convenience function with dataset_name.""" @@ -1486,7 +1486,7 @@ def test_list_dataset_projects_with_no_params() -> None: list_dataset_projects() -@patch("galileo.datasets.get_dataset_datasets_dataset_id_get") +@patch("splunk_ao.datasets.get_dataset_datasets_dataset_id_get") def test_list_dataset_projects_with_nonexistent_dataset(get_dataset_mock: Mock) -> None: """Test list_dataset_projects with a dataset that doesn't exist.""" # Mock dataset retrieval - return None to simulate nonexistent dataset @@ -1496,7 +1496,7 @@ def test_list_dataset_projects_with_nonexistent_dataset(get_dataset_mock: Mock) list_dataset_projects(dataset_id="nonexistent-dataset") -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_normalizes_ground_truth_to_output(create_dataset_datasets_post_mock: Mock) -> None: """Test that create_dataset normalizes ground_truth field to output before sending to API.""" # Given: a dataset with ground_truth fields @@ -1548,7 +1548,7 @@ def test_create_dataset_normalizes_ground_truth_to_output(create_dataset_dataset assert row["output"] in ["Europe", "Asia"], f"Expected output value, got {row['output']}" -@patch("galileo.datasets.create_dataset_datasets_post") +@patch("splunk_ao.datasets.create_dataset_datasets_post") def test_create_dataset_does_not_mutate_caller_dicts(create_dataset_datasets_post_mock: Mock) -> None: """Test that create_dataset does not mutate the caller's input dicts.""" # Given: a dataset with ground_truth in caller-owned dicts @@ -1589,7 +1589,7 @@ def test_create_dataset_does_not_mutate_caller_dicts(create_dataset_datasets_pos def test_normalize_dataset_rows_renames_ground_truth_to_output() -> None: - from galileo.utils.datasets import normalize_dataset_rows + from splunk_ao.utils.datasets import normalize_dataset_rows # Given: rows with ground_truth rows = [{"input": "Q1", "ground_truth": "A1"}, {"input": "Q2", "ground_truth": "A2"}] @@ -1602,7 +1602,7 @@ def test_normalize_dataset_rows_renames_ground_truth_to_output() -> None: def test_normalize_dataset_rows_output_takes_precedence() -> None: - from galileo.utils.datasets import normalize_dataset_rows + from splunk_ao.utils.datasets import normalize_dataset_rows # Given: a row with both output and ground_truth rows = [{"input": "Q1", "output": "correct", "ground_truth": "ignored"}] @@ -1615,7 +1615,7 @@ def test_normalize_dataset_rows_output_takes_precedence() -> None: def test_normalize_dataset_rows_does_not_mutate_caller_dicts() -> None: - from galileo.utils.datasets import normalize_dataset_rows + from splunk_ao.utils.datasets import normalize_dataset_rows # Given: caller-owned dicts original = {"input": "Q1", "ground_truth": "A1"} @@ -1629,7 +1629,7 @@ def test_normalize_dataset_rows_does_not_mutate_caller_dicts() -> None: def test_normalize_dataset_rows_passes_through_rows_without_ground_truth() -> None: - from galileo.utils.datasets import normalize_dataset_rows + from splunk_ao.utils.datasets import normalize_dataset_rows # Given: rows that already use output rows = [{"input": "Q1", "output": "A1"}, {"input": "Q2", "custom_col": "val"}] @@ -1646,8 +1646,8 @@ def test_normalize_dataset_rows_passes_through_rows_without_ground_truth() -> No # --------------------------------------------------------------------------- -@patch("galileo.datasets.update_dataset_content_datasets_dataset_id_content_patch") -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.update_dataset_content_datasets_dataset_id_content_patch") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test_add_rows_normalizes_ground_truth_to_output(get_content_mock: Mock, patch_mock: Mock) -> None: """Test that add_rows normalizes ground_truth to output before sending to the API.""" from http import HTTPStatus @@ -1674,8 +1674,8 @@ def test_add_rows_normalizes_ground_truth_to_output(get_content_mock: Mock, patc assert sent_values == {"input": "Which continent is Morocco in?", "output": "Africa"} -@patch("galileo.datasets.update_dataset_content_datasets_dataset_id_content_patch") -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.update_dataset_content_datasets_dataset_id_content_patch") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test_add_rows_does_not_mutate_caller_dicts(get_content_mock: Mock, patch_mock: Mock) -> None: """Test that add_rows does not mutate the caller's input dicts.""" from http import HTTPStatus @@ -1697,7 +1697,7 @@ def test_add_rows_does_not_mutate_caller_dicts(get_content_mock: Mock, patch_moc assert original == {"input": "Q1", "ground_truth": "A1"} -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test_get_content_returns_none_when_api_returns_none(get_content_mock: Mock) -> None: """Test that get_content() handles None API response without crashing.""" # Given: the API returns None @@ -1713,7 +1713,7 @@ def test_get_content_returns_none_when_api_returns_none(get_content_mock: Mock) assert content is None -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test_get_content_syncs_dataset_column_names_after_remap(get_content_mock: Mock) -> None: """Test that get_content() updates dataset.column_names to the remapped names.""" # Given: the API returns content with 'output' as a column name @@ -1730,7 +1730,7 @@ def test_get_content_syncs_dataset_column_names_after_remap(get_content_mock: Mo assert ds.dataset.column_names == ["input", "ground_truth", "generated_output"] -@patch("galileo.datasets.get_dataset_content_datasets_dataset_id_content_get") +@patch("splunk_ao.datasets.get_dataset_content_datasets_dataset_id_content_get") def test_get_content_remaps_output_to_ground_truth(get_content_mock: Mock) -> None: """Test that get_content() remaps 'output' to 'ground_truth' in column_names and row values.""" # Given: the API returns content with 'output' as the column name diff --git a/tests/test_decorator.py b/tests/test_decorator.py index ede25803..1afb3868 100644 --- a/tests/test_decorator.py +++ b/tests/test_decorator.py @@ -5,12 +5,12 @@ import pytest from pydantic import BaseModel -from galileo import Message, MessageRole, galileo_context, log, start_session -from galileo.decorator import _session_id_context -from galileo.schema.content_blocks import DataContentBlock, TextContentBlock from galileo_core.schemas.logging.span import AgentSpan, LlmSpan, RetrieverSpan, ToolSpan, WorkflowSpan from galileo_core.schemas.shared.document import Document from galileo_core.schemas.shared.multimodal import ContentModality +from splunk_ao import Message, MessageRole, galileo_context, log, start_session +from splunk_ao.decorator import _session_id_context +from splunk_ao.schema.content_blocks import DataContentBlock, TextContentBlock from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -21,9 +21,9 @@ def reset_context(): galileo_context.reset() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_context_reset( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -54,9 +54,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_log_stream() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_context_init( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -75,9 +75,9 @@ def test_decorator_context_init( assert galileo_context.get_current_log_stream() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_context_flush( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -109,9 +109,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_span_stack() == [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_context_flush_specific_project_and_log_stream( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -158,9 +158,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_trace() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_context_flush_all( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -205,9 +205,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_span_stack() == [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_llm_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -232,9 +232,9 @@ def llm_call(query: str) -> str: assert payload.traces[0].spans[0].output == Message(content="response", role=MessageRole.assistant) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_span_output_int( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -259,9 +259,9 @@ def my_function(arg1, arg2): assert payload.traces[0].spans[0].output == "3" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_span_io_object( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -294,9 +294,9 @@ def my_function(system: Message, user: Message): assert payload.traces[0].spans[0].output == '{"content": "response", "metadata": {"arg1": "val1", "arg2": "val2"}}' -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_tool_span_io_object( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -329,9 +329,9 @@ def my_function(system: Message, user: Message): assert payload.traces[0].spans[0].output == '{"content": "response", "metadata": {"arg1": "val1", "arg2": "val2"}}' -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_agent_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -356,9 +356,9 @@ def my_function(arg1: str, arg2: str) -> str: assert payload.traces[0].spans[0].output == "arg1 arg2" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_agent_span_with_agent_type( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -384,9 +384,9 @@ def my_function(arg1: str, arg2: str) -> str: assert payload.traces[0].spans[0].agent_type == "planner" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_agent_span_with_nested_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -421,9 +421,9 @@ def my_function(arg1: str, arg2: str): assert payload.traces[0].spans[0].spans[0].output == "arg1" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_nested_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -456,9 +456,9 @@ def nested_call(nested_query: str): assert payload.traces[0].spans[0].spans[0].output == Message(content="response", role=MessageRole.assistant) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_multiple_nested_spans( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -494,9 +494,9 @@ def nested_call(nested_query: str) -> str: assert payload.traces[0].spans[0].spans[0].output == Message(content="response", role=MessageRole.assistant) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_retriever_span_str( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -518,9 +518,9 @@ def retriever_call(query: str) -> str: assert payload.traces[0].spans[0].output == [Document(content="response1", metadata=None)] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_retriever_span_list_str( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -545,9 +545,9 @@ def retriever_call(query: str): ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_retriever_span_list_dict( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -572,9 +572,9 @@ def retriever_call(query: str): ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_retriever_span_list_document( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -599,9 +599,9 @@ def retriever_call(query: str): ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_we_should_create_trace_but_reraise_exception( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -624,9 +624,9 @@ def foo() -> NoReturn: assert len(payload.traces[0].spans) == 1 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_start_session( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -653,9 +653,9 @@ def foo() -> str: assert payload.session_id == UUID("6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_standalone_start_session( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -684,9 +684,9 @@ def foo() -> str: assert payload.session_id == UUID("6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_start_session_empty_values( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -711,9 +711,9 @@ def foo() -> str: assert payload.session_id == UUID("6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_clear_session( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -742,9 +742,9 @@ def foo() -> str: assert payload.session_id is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_set_session( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -785,9 +785,9 @@ class ComplexPydanticModel(BaseModel): items: list = [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_input_serialization_deserialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -816,9 +816,9 @@ def my_function(complex_input: dict) -> str: ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_llm_span_list_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -842,9 +842,9 @@ def llm_call_returning_list(query: str): assert span.output.content == '["response1", "response2", "response3"]' -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_llm_span_tuple_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -869,9 +869,9 @@ def llm_call_returning_tuple(query: str): assert span.output.content == '["response1", "response2"]' -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_llm_span_dict_output_preserved( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -897,9 +897,9 @@ def llm_call_returning_dict(query: str): assert '"number": 42' in span.output.content -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_span_complex_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -928,9 +928,9 @@ def workflow_with_complex_output(query: str): assert span.output == expected_content -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_pydantic_model_input_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -957,9 +957,9 @@ def process_model(model: TestPydanticModel) -> str: assert '"optional_field"' not in span.input -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_pydantic_model_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -984,9 +984,9 @@ def create_model(name: str, value: int): assert '"value": 123' in span.output -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_null_output_handling( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1010,9 +1010,9 @@ def function_returning_none(query: str) -> None: assert span.output is None or span.output == "" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_tool_span_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1038,9 +1038,9 @@ def tool_with_complex_output(input_data: str): assert '"items": [1, 2, 3]' in span.output -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_agent_span_output_serialization( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1066,9 +1066,9 @@ def agent_with_complex_output(query: str): assert '"actions": ["analyze", "respond"]' in span.output -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_content_blocks_output_preserved( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1103,9 +1103,9 @@ def workflow_returning_content_blocks(query: str): assert isinstance(span_output, list) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_message_list_output_serialized( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1138,9 +1138,9 @@ def workflow_returning_messages(query: str): # ============================================================================ -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_init_default( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1154,9 +1154,9 @@ def test_mode_context_init_default( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_init_explicit( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1170,9 +1170,9 @@ def test_mode_context_init_explicit( assert galileo_context.get_current_mode() == "distributed" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_call_default( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1185,9 +1185,9 @@ def test_mode_context_call_default( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_call_explicit( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1200,9 +1200,9 @@ def test_mode_context_call_explicit( assert galileo_context.get_current_mode() == "distributed" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_nested_push_pop( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1223,9 +1223,9 @@ def test_mode_context_nested_push_pop( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_multiple_nested_levels( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1253,9 +1253,9 @@ def test_mode_context_multiple_nested_levels( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_context_reset( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1271,9 +1271,9 @@ def test_mode_context_reset( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_flush_with_explicit_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1302,9 +1302,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_trace() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mode_flush_different_mode_no_reset( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1333,9 +1333,9 @@ def llm_call(query: str) -> str: assert galileo_context.get_current_trace() == current_trace -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") @patch.dict("os.environ", {"SPLUNK_AO_MODE": "distributed"}) def test_mode_from_environment_variable( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context @@ -1351,9 +1351,9 @@ def test_mode_from_environment_variable( assert galileo_context.get_current_mode() == "distributed" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") @patch.dict("os.environ", {"SPLUNK_AO_MODE": "distributed"}) def test_mode_explicit_overrides_environment( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context @@ -1369,9 +1369,9 @@ def test_mode_explicit_overrides_environment( assert galileo_context.get_current_mode() == "batch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_logger_instance_with_explicit_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1395,9 +1395,9 @@ def test_get_logger_instance_with_explicit_mode( assert logger_distributed.mode == "distributed" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_multiple_workflow_calls_create_one_trace_with_multiple_spans( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1450,9 +1450,9 @@ def process_query(query: str) -> str: assert len(logger.traces) == 0 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_id_context_manager( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1476,9 +1476,9 @@ def foo() -> str: assert payload.session_id == UUID(test_session_id) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_id_nested_context_stacking( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1506,9 +1506,9 @@ def test_session_id_nested_context_stacking( assert galileo_context.get_logger_instance().session_id is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_id_cleared_on_reset_and_init( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1532,9 +1532,9 @@ def test_session_id_cleared_on_reset_and_init( assert galileo_context.get_logger_instance().session_id is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_start_session_overrides_context_session( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1554,9 +1554,9 @@ def test_start_session_overrides_context_session( assert _session_id_context.get() == new_session_id -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_on_error_called_when_flush_raises( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1585,9 +1585,9 @@ def llm_call(query: str) -> str: assert isinstance(on_error.call_args[0][0], Exception) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_warns_when_flush_raises_without_on_error( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1607,15 +1607,15 @@ def llm_call(query: str) -> str: # When/Then: flush does not raise; a warning is logged instead - with patch("galileo.decorator._logger") as mock_logger: + with patch("splunk_ao.decorator._logger") as mock_logger: galileo_context.flush() mock_logger.warning.assert_called_once() assert "flush failed" in mock_logger.warning.call_args[0][0] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_on_error_callback_raises_is_swallowed( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1637,15 +1637,15 @@ def llm_call(query: str) -> str: llm_call(query="input") # When/Then: flush does not raise even though the callback raises - with patch("galileo.decorator._logger") as mock_logger: + with patch("splunk_ao.decorator._logger") as mock_logger: galileo_context.flush(on_error=bad_callback) # must not raise mock_logger.warning.assert_called_once() assert "on_error callback raised" in mock_logger.warning.call_args[0][0] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_on_error_logs_at_debug_not_warning( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -1664,7 +1664,7 @@ def llm_call(query: str) -> str: llm_call(query="input") # When: flush is called with on_error - with patch("galileo.decorator._logger") as mock_logger: + with patch("splunk_ao.decorator._logger") as mock_logger: galileo_context.flush(on_error=Mock()) # Then: debug is called, not warning diff --git a/tests/test_decorator_distributed.py b/tests/test_decorator_distributed.py index 51f6c8c0..633b9bab 100644 --- a/tests/test_decorator_distributed.py +++ b/tests/test_decorator_distributed.py @@ -6,14 +6,14 @@ import pytest -from galileo import Message, MessageRole, galileo_context, log -from galileo.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER -from galileo.decorator import _parent_id_context, _trace_id_context -from galileo.schema.content_blocks import DataContentBlock, TextContentBlock -from galileo.schema.trace import SpanUpdateRequest, TraceUpdateRequest -from galileo.tracing import get_tracing_headers from galileo_core.schemas.shared.document import Document from galileo_core.schemas.shared.multimodal import ContentModality +from splunk_ao import Message, MessageRole, galileo_context, log +from splunk_ao.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER +from splunk_ao.decorator import _parent_id_context, _trace_id_context +from splunk_ao.schema.content_blocks import DataContentBlock, TextContentBlock +from splunk_ao.schema.trace import SpanUpdateRequest, TraceUpdateRequest +from splunk_ao.tracing import get_tracing_headers from tests.testutils.setup import ( setup_mock_logstreams_client, setup_mock_projects_client, @@ -42,9 +42,9 @@ def set_distributed_mode(): os.environ["SPLUNK_AO_MODE"] = original -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_get_tracing_headers( mock_traces_client: Mock, mock_projects_client: Mock, @@ -76,9 +76,9 @@ def orchestrator(query: str) -> dict: assert headers[TRACE_ID_HEADER] == str(logger.traces[0].id) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_with_middleware_context( mock_traces_client: Mock, mock_projects_client: Mock, @@ -118,9 +118,9 @@ def downstream_service(query: str) -> str: assert logger.traces[0].name == "stub_trace" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_updates_trace_with_output_and_duration( mock_traces_client: Mock, mock_projects_client: Mock, @@ -181,9 +181,9 @@ def my_function(input_value: str) -> str: assert trace_request.is_complete, "Trace should be marked complete after flush" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_server_side_does_not_conclude_trace( mock_traces_client: Mock, mock_projects_client: Mock, @@ -229,9 +229,9 @@ def downstream_service(query: str) -> str: assert logger.traces[0].name == "stub_trace" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_client_and_server_side_behavior( mock_traces_client: Mock, mock_projects_client: Mock, @@ -320,9 +320,9 @@ def server_function(query: str) -> str: assert logger_server.traces[0].name == "stub_trace" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_span_output_is_set( mock_traces_client: Mock, mock_projects_client: Mock, @@ -370,9 +370,9 @@ def my_workflow(input_value: str) -> str: mock_traces_client_instance.update_span.assert_called() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_both_trace_and_workflow_span_have_output( mock_traces_client: Mock, mock_projects_client: Mock, @@ -436,9 +436,9 @@ def my_function(input_value: str) -> str: assert trace_request.is_complete, "Trace should be marked complete after flush" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_workflow_span_empty_string_output_is_set( mock_traces_client: Mock, mock_projects_client: Mock, @@ -480,9 +480,9 @@ def my_workflow(input_value: str) -> str: assert request.output == "", "Workflow span output should be set to empty string, not None" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_trace_duration_is_set_and_accumulates( mock_traces_client: Mock, mock_projects_client: Mock, @@ -543,9 +543,9 @@ def workflow_step_2() -> str: ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_distributed_content_blocks_preserved_on_trace( mock_traces_client: Mock, mock_projects_client: Mock, @@ -589,9 +589,9 @@ def workflow_with_content_blocks(query: str): assert "image" in trace_request.output -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_distributed_messages_serialized_on_trace( mock_traces_client: Mock, mock_projects_client: Mock, @@ -630,9 +630,9 @@ def workflow_with_messages(query: str): assert "Hi!" in trace_request.output -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_decorator_distributed_documents_serialized_on_trace( mock_traces_client: Mock, mock_projects_client: Mock, diff --git a/tests/test_deprecations.py b/tests/test_deprecations.py index c21491c7..6183d37c 100644 --- a/tests/test_deprecations.py +++ b/tests/test_deprecations.py @@ -12,14 +12,14 @@ def test_galileo_scorers_attribute_access_emits_deprecation_warning(): """Accessing GalileoScorers. should emit a DeprecationWarning.""" with pytest.warns(DeprecationWarning, match="GalileoScorers is deprecated"): - from galileo.schema.metrics import GalileoScorers + from splunk_ao.schema.metrics import GalileoScorers _ = GalileoScorers.correctness def test_galileo_metrics_attribute_access_does_not_warn(): """Accessing SplunkAOMetrics. should NOT emit a DeprecationWarning.""" - from galileo.schema.metrics import SplunkAOMetrics + from splunk_ao.schema.metrics import SplunkAOMetrics with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") @@ -30,14 +30,14 @@ def test_galileo_metrics_attribute_access_does_not_warn(): def test_top_level_imported_galileo_scorers_emits_deprecation_on_access(): """Importing GalileoScorers from the top-level package and accessing attribute should warn.""" with pytest.warns(DeprecationWarning, match="GalileoScorers is deprecated"): - from galileo import GalileoScorers + from splunk_ao import GalileoScorers _ = GalileoScorers.correctness def test_galileo_scorers_callable_and_lookup_delegate(): """GalileoScorers('correctness') and GalileoScorers['correctness'] should work and warn.""" - from galileo.schema.metrics import GalileoScorers + from splunk_ao.schema.metrics import GalileoScorers # Value-based lookup uses the ScorerName value (internal name) with pytest.warns(DeprecationWarning, match="GalileoScorers is deprecated"): @@ -55,7 +55,7 @@ def test_galileo_scorers_callable_and_lookup_delegate(): def test_galileo_scorers_isinstance_check(): """isinstance checks with GalileoScorers should work — delegates to ScorerName.""" - from galileo.schema.metrics import GalileoScorers + from splunk_ao.schema.metrics import GalileoScorers assert isinstance(ScorerName.correctness, GalileoScorers) assert not isinstance("not a scorer", GalileoScorers) @@ -63,14 +63,14 @@ def test_galileo_scorers_isinstance_check(): def test_galileo_scorers_issubclass_check(): """issubclass checks with GalileoScorers should work — delegates to ScorerName.""" - from galileo.schema.metrics import GalileoScorers + from splunk_ao.schema.metrics import GalileoScorers assert issubclass(type(ScorerName.correctness), GalileoScorers) def test_galileo_scorers_returns_scorer_name_members(): """GalileoScorers attribute access should return ScorerName enum members.""" - from galileo.schema.metrics import GalileoScorers + from splunk_ao.schema.metrics import GalileoScorers with pytest.warns(DeprecationWarning, match="GalileoScorers is deprecated"): scorer = GalileoScorers.correctness diff --git a/tests/test_experiment.py b/tests/test_experiment.py index 75e934d2..47b5953a 100644 --- a/tests/test_experiment.py +++ b/tests/test_experiment.py @@ -5,19 +5,19 @@ import pytest -from galileo.exceptions import NotFoundError -from galileo.experiment import Experiment from galileo.resources.models import ExperimentResponse, PromptRunSettings from galileo.resources.models.column_category import ColumnCategory from galileo.resources.models.column_info import ColumnInfo from galileo.resources.models.data_type import DataType -from galileo.schema.metrics import SplunkAOMetrics -from galileo.search import RecordType -from galileo.shared.base import SyncState -from galileo.shared.column import ColumnCollection -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError -from galileo.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo -from galileo.shared.query_result import QueryResult +from splunk_ao.exceptions import NotFoundError +from splunk_ao.experiment import Experiment +from splunk_ao.schema.metrics import SplunkAOMetrics +from splunk_ao.search import RecordType +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.column import ColumnCollection +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError +from splunk_ao.shared.experiment_result import ExperimentRunResult, ExperimentStatusInfo +from splunk_ao.shared.query_result import QueryResult @pytest.fixture @@ -179,7 +179,7 @@ def test_init_with_both_prompt_and_prompt_name_warns_and_prompt_wins( """Test that providing both 'prompt' and 'prompt_name' logs a warning and 'prompt' takes precedence.""" # Given: both prompt and prompt_name provided # When: creating an experiment while capturing warnings on the experiment logger - with caplog.at_level(logging.WARNING, logger="galileo.experiment"): + with caplog.at_level(logging.WARNING, logger="splunk_ao.experiment"): experiment = Experiment( name="Test Experiment", dataset_name="test-dataset", @@ -201,11 +201,11 @@ def test_init_with_both_prompt_and_prompt_name_warns_and_prompt_wins( class TestExperimentEnvFallback: """Test suite for Experiment environment variable fallback behavior.""" - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_uses_env_fallback_when_no_project_specified( self, mock_experiments_class: MagicMock, @@ -244,7 +244,7 @@ def test_create_uses_env_fallback_when_no_project_specified( assert experiment.project_id == mock_project.id assert experiment.is_synced() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_raises_named_error_when_project_name_not_found( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -264,7 +264,7 @@ def test_create_raises_named_error_when_project_name_not_found( with pytest.raises(ResourceNotFoundError, match=r'Project "my-nonexistent-project" not found'): experiment.create() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_raises_error_when_no_project_and_no_env_fallback( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -279,10 +279,10 @@ def test_create_raises_error_when_no_project_and_no_env_fallback( with pytest.raises(ResourceNotFoundError, match="No project specified"): experiment.create() - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_without_prompt_succeeds( self, mock_experiments_class: MagicMock, @@ -320,8 +320,8 @@ def test_create_without_prompt_succeeds( assert kwargs.get("prompt_template") is None assert kwargs.get("prompt_settings") is None - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_get_uses_env_fallback_when_no_project_specified( self, mock_experiments_class: MagicMock, @@ -349,7 +349,7 @@ def test_get_uses_env_fallback_when_no_project_specified( mock_projects_service.get_with_env_fallbacks.assert_called_once() assert experiment.project_id == mock_project.id - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_raises_error_when_no_project_and_no_env_fallback( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -363,8 +363,8 @@ def test_get_raises_error_when_no_project_and_no_env_fallback( with pytest.raises(ResourceNotFoundError, match="No project specified"): Experiment.get(name="Test Experiment") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_list_uses_env_fallback_when_no_project_specified( self, mock_experiments_class: MagicMock, @@ -391,7 +391,7 @@ def test_list_uses_env_fallback_when_no_project_specified( mock_projects_service.get_with_env_fallbacks.assert_called_once() assert experiments == [] - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_raises_error_when_no_project_and_no_env_fallback( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -405,7 +405,7 @@ def test_list_raises_error_when_no_project_and_no_env_fallback( with pytest.raises(ResourceNotFoundError, match="No project specified"): Experiment.list() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_no_project_no_env_does_not_leak_value_error( self, mock_projects_class: MagicMock, reset_configuration: None, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -430,11 +430,11 @@ def test_list_no_project_no_env_does_not_leak_value_error( class TestExperimentCreate: """Test suite for Experiment.create() method.""" - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_persists_and_triggers_experiment( self, mock_experiments_class: MagicMock, @@ -480,11 +480,11 @@ def test_create_persists_and_triggers_experiment( assert experiment.is_synced() assert experiment._run_result is not None - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_handles_existing_experiment_with_timestamp( self, mock_experiments_class: MagicMock, @@ -526,11 +526,11 @@ def test_create_handles_existing_experiment_with_timestamp( assert "Test Experiment" in call_args.kwargs["name"] assert call_args.kwargs["name"] != "Test Experiment" - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_handles_api_failure( self, mock_experiments_class: MagicMock, @@ -568,11 +568,11 @@ def test_create_handles_api_failure( assert experiment.sync_state == SyncState.FAILED_SYNC - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_fills_default_prompt_settings_for_prompt_template( self, mock_experiments_class: MagicMock, @@ -621,11 +621,11 @@ def test_create_fills_default_prompt_settings_for_prompt_template( assert call_kwargs["prompt_settings"].temperature == 0.8 assert call_kwargs["prompt_settings"].max_tokens == 256 - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_preserves_user_prompt_settings_when_overriding_model_alias( self, mock_experiments_class: MagicMock, @@ -678,11 +678,11 @@ def test_create_preserves_user_prompt_settings_when_overriding_model_alias( assert effective.max_tokens == 123 assert effective.top_p == 0.9 - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_treats_not_found_as_no_existing_experiment( self, mock_experiments_class: MagicMock, @@ -732,8 +732,8 @@ def test_create_treats_not_found_as_no_existing_experiment( class TestExperimentGet: """Test suite for Experiment.get() class method.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_get_retrieves_experiment_by_name( self, mock_experiments_class: MagicMock, @@ -762,8 +762,8 @@ def test_get_retrieves_experiment_by_name( assert experiment.is_synced() assert experiment.project_id == mock_project.id - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_get_returns_none_when_not_found( self, mock_experiments_class: MagicMock, @@ -791,8 +791,8 @@ def test_get_returns_none_when_not_found( class TestExperimentList: """Test suite for Experiment.list() class method.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_list_retrieves_all_experiments( self, mock_experiments_class: MagicMock, @@ -859,7 +859,7 @@ def test_run_returns_stored_result_from_create(self, reset_configuration: None) assert isinstance(run_result, ExperimentRunResult) assert run_result.link == "http://test.com/results" - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.ExperimentsService") def test_run_returns_fallback_result_when_no_stored_result( self, mock_experiments_class: MagicMock, reset_configuration: None ) -> None: @@ -891,11 +891,11 @@ def test_run_raises_error_when_not_created(self, reset_configuration: None) -> N with pytest.raises(ValueError, match="Experiment must be created before running"): experiment.run() - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_run_raises_error_on_second_call_after_result_consumed( self, mock_experiments_class: MagicMock, @@ -940,11 +940,11 @@ def test_run_raises_error_on_second_call_after_result_consumed( with pytest.raises(ValueError, match="has already been run"): experiment.run() - @patch("galileo.experiment.create_metric_configs") - @patch("galileo.experiment.get_prompt") - @patch("galileo.experiment.load_dataset_and_records") - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.experiment.ExperimentsService") + @patch("splunk_ao.experiment.create_metric_configs") + @patch("splunk_ao.experiment.get_prompt") + @patch("splunk_ao.experiment.load_dataset_and_records") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.experiment.ExperimentsService") def test_create_run_create_run_resets_consumed_flag( self, mock_experiments_class: MagicMock, @@ -999,7 +999,7 @@ def test_create_run_create_run_resets_consumed_flag( class TestExperimentQuery: """Test suite for Experiment query methods.""" - @patch("galileo.experiment.Search") + @patch("splunk_ao.experiment.Search") def test_query_returns_query_result( self, mock_search_class: MagicMock, synced_experiment: Experiment, reset_configuration: None ) -> None: @@ -1030,7 +1030,7 @@ def test_query_raises_error_when_not_synced(self, reset_configuration: None) -> class TestExperimentRelationships: """Test suite for Experiment relationship properties.""" - @patch("galileo.project.Project") + @patch("splunk_ao.project.Project") def test_project_property_returns_project( self, mock_project_class: MagicMock, @@ -1061,8 +1061,8 @@ def test_relationship_properties_return_none_when_not_set( class TestExperimentLifecycle: """Test suite for Experiment lifecycle methods (refresh, delete).""" - @patch("galileo.experiment.SplunkAOConfig") - @patch("galileo.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") + @patch("splunk_ao.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") def test_refresh_updates_attributes( self, mock_get_experiment_api: MagicMock, @@ -1107,8 +1107,8 @@ def test_refresh_updates_attributes( assert synced_experiment._experiment_response is mock_experiment_response assert synced_experiment.is_synced() - @patch("galileo.experiment.SplunkAOConfig") - @patch("galileo.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") + @patch("splunk_ao.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") def test_refresh_sets_failed_sync_on_not_found( self, mock_get_experiment_api: MagicMock, @@ -1128,8 +1128,8 @@ def test_refresh_sets_failed_sync_on_not_found( assert synced_experiment.sync_state == SyncState.FAILED_SYNC - @patch("galileo.experiment.SplunkAOConfig") - @patch("galileo.experiment.delete_experiment_projects_project_id_experiments_experiment_id_delete") + @patch("splunk_ao.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.delete_experiment_projects_project_id_experiments_experiment_id_delete") def test_delete_removes_experiment( self, mock_delete_api: MagicMock, @@ -1165,7 +1165,7 @@ class TestExperimentQueryMethods: "method_name,record_type", [("get_traces", RecordType.TRACE), ("get_sessions", RecordType.SESSION), ("get_spans", RecordType.SPAN)], ) - @patch("galileo.experiment.Search") + @patch("splunk_ao.experiment.Search") def test_query_convenience_methods( self, mock_search_class: MagicMock, @@ -1211,7 +1211,7 @@ def test_set_prompt( synced_experiment.set_prompt(**kwargs) assert getattr(synced_experiment, expected_attr) == expected_value - @patch("galileo.experiment.get_prompt") + @patch("splunk_ao.experiment.get_prompt") def test_get_prompt_template_settings( self, mock_get_prompt: MagicMock, synced_experiment: Experiment, reset_configuration: None ) -> None: @@ -1235,7 +1235,7 @@ class TestExperimentStatusMethods: """Test suite for Experiment status methods.""" @pytest.mark.parametrize("has_records,expected_result", [(True, True), (False, False)]) - @patch("galileo.experiment.Search") + @patch("splunk_ao.experiment.Search") def test_has_traces( self, mock_search_class: MagicMock, @@ -1255,8 +1255,8 @@ def test_has_traces( assert synced_experiment.has_traces() is expected_result - @patch("galileo.experiment.SplunkAOConfig") - @patch("galileo.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") + @patch("splunk_ao.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") def test_get_status_returns_status_info( self, mock_get_experiment_api: MagicMock, @@ -1379,7 +1379,7 @@ def test_metric_aggregates_returns_populated_dict( assert result[scorer_uuid].avg == 0.85 assert "cost" in result - @patch("galileo.experiment._logger") + @patch("splunk_ao.experiment._logger") def test_aggregate_metrics_logs_deprecation_warning( self, mock_logger: MagicMock, synced_experiment: Experiment, reset_configuration: None ) -> None: @@ -1402,8 +1402,8 @@ def test_aggregate_metrics_logs_deprecation_warning( class TestMetricColumns: """Tests for Experiment.experiment_columns.""" - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_experiment_columns_returns_column_collection( self, mock_config_class: MagicMock, @@ -1497,8 +1497,8 @@ def test_returns_none_when_metric_aggregates_empty( # Then: None is returned without error assert result is None - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_lookup_by_galileo_metrics_enum( self, mock_config_class: MagicMock, @@ -1520,8 +1520,8 @@ def test_lookup_by_galileo_metrics_enum( assert result is not None assert result.avg == 0.85 - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_lookup_by_label_string( self, mock_config_class: MagicMock, @@ -1543,8 +1543,8 @@ def test_lookup_by_label_string( assert result is not None assert result.avg == 0.85 - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_lookup_by_metric_key_alias( self, mock_config_class: MagicMock, @@ -1577,8 +1577,8 @@ def test_lookup_by_uuid_string(self, synced_experiment: Experiment, reset_config assert result is not None assert result.avg == 0.85 - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_returns_none_for_unknown_metric( self, mock_config_class: MagicMock, @@ -1599,8 +1599,8 @@ def test_returns_none_for_unknown_metric( # Then: None is returned assert result is None - @patch("galileo.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.experiments_available_columns_projects_project_id_experiments_available_columns_post") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_label_takes_priority_over_alias( self, mock_config_class: MagicMock, @@ -1651,9 +1651,9 @@ def test_label_takes_priority_over_alias( class TestExperimentTagging: """Test suite for Experiment tagging functionality.""" - @patch("galileo.experiment.SplunkAOConfig") - @patch("galileo.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") - @patch("galileo.experiment.upsert_experiment_tag") + @patch("splunk_ao.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.get_experiment_projects_project_id_experiments_experiment_id_get") + @patch("splunk_ao.experiment.upsert_experiment_tag") def test_add_tag_upserts_tag( self, mock_upsert_tag: MagicMock, @@ -1708,7 +1708,7 @@ class TestExperimentColumns: ("session_columns", "sessions_available_columns_projects_project_id_sessions_available_columns_post"), ], ) - @patch("galileo.experiment.SplunkAOConfig") + @patch("splunk_ao.experiment.SplunkAOConfig") def test_column_properties_return_collection( self, mock_config_class: MagicMock, @@ -1722,7 +1722,7 @@ def test_column_properties_return_collection( mock_config_class.get.return_value = mock_config # Patch the specific API function - with patch(f"galileo.experiment.{api_function}") as mock_api: + with patch(f"splunk_ao.experiment.{api_function}") as mock_api: mock_response = MagicMock() mock_response.columns = [] mock_api.sync.return_value = mock_response diff --git a/tests/test_experiment_tags.py b/tests/test_experiment_tags.py index 15bc20c4..c9f55b19 100644 --- a/tests/test_experiment_tags.py +++ b/tests/test_experiment_tags.py @@ -5,15 +5,15 @@ import pytest -from galileo.experiment_tags import ( +from galileo.resources.models.delete_run_response import DeleteRunResponse +from galileo.resources.models.run_tag_db import RunTagDB +from splunk_ao.experiment_tags import ( ExperimentTags, ExperimentTagsAPIException, delete_experiment_tag, get_experiment_tags, upsert_experiment_tag, ) -from galileo.resources.models.delete_run_response import DeleteRunResponse -from galileo.resources.models.run_tag_db import RunTagDB @pytest.fixture diff --git a/tests/test_experiments.py b/tests/test_experiments.py index 19948482..e16e2ed5 100644 --- a/tests/test_experiments.py +++ b/tests/test_experiments.py @@ -11,21 +11,9 @@ import pytest from time_machine import travel -import galileo.experiments -import galileo.jobs -import galileo.utils.datasets -from galileo import galileo_context -from galileo.decorator import SPAN_TYPE -from galileo.experiments import ( - Experiments, - create_experiment, - get_experiment, - get_experiments, - list_experiment_groups, - run_experiment, -) -from galileo.projects import Project -from galileo.prompts import PromptTemplate +import splunk_ao.experiments +import splunk_ao.jobs +import splunk_ao.utils.datasets from galileo.resources.models import ( BasePromptTemplateResponse, BasePromptTemplateVersionResponse, @@ -44,13 +32,25 @@ ValidationError, ) from galileo.resources.types import UNSET -from galileo.schema.datasets import DatasetRecord -from galileo.schema.experiment_group import ExperimentGroupResponse -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig -from galileo.utils.datasets import load_dataset_and_records -from galileo.utils.exceptions import _format_http_validation_error from galileo_core.schemas.logging.span import Span, StepWithChildSpans from galileo_core.schemas.shared.metric import MetricValueType +from splunk_ao import galileo_context +from splunk_ao.decorator import SPAN_TYPE +from splunk_ao.experiments import ( + Experiments, + create_experiment, + get_experiment, + get_experiments, + list_experiment_groups, + run_experiment, +) +from splunk_ao.projects import Project +from splunk_ao.prompts import PromptTemplate +from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.schema.experiment_group import ExperimentGroupResponse +from splunk_ao.schema.metrics import LocalMetricConfig, SplunkAOMetrics +from splunk_ao.utils.datasets import load_dataset_and_records +from splunk_ao.utils.exceptions import _format_http_validation_error from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -167,7 +167,7 @@ def mock_scorer_version_response(): class TestExperiments: - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_create(self, galileo_resources_api_create_experiment: Mock) -> None: now = datetime(2020, 1, 1).strftime("%Y-%m-%dT%H:%M:%S.%fZ") galileo_resources_api_create_experiment.sync = Mock( @@ -187,7 +187,7 @@ def test_create(self, galileo_resources_api_create_experiment: Mock) -> None: assert experiment.project_id == "test" galileo_resources_api_create_experiment.sync.assert_called_once_with(project_id="test", client=ANY, body=ANY) - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_create_raises_value_error_with_clear_message_on_invalid_model_alias( self, galileo_resources_api_create_experiment: Mock ) -> None: @@ -213,7 +213,7 @@ def test_create_raises_value_error_with_clear_message_on_invalid_model_alias( project_id="test", name="test_experiment", prompt_settings=PromptRunSettings(model_alias="gpt-4o-mini") ) - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_create_error_message_contains_field_and_msg_on_422( self, galileo_resources_api_create_experiment: Mock ) -> None: @@ -240,7 +240,7 @@ def test_create_error_message_contains_field_and_msg_on_422( assert "model_alias" in msg assert "gpt-4o-mini" in msg - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_create_raises_value_error_when_api_returns_string_detail( self, galileo_resources_api_create_experiment: Mock ) -> None: @@ -256,7 +256,7 @@ def test_create_raises_value_error_when_api_returns_string_detail( project_id="test", name="test_experiment", prompt_settings=PromptRunSettings(model_alias="gpt-4o-mini") ) - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_create_with_dict_prompt_settings(self, galileo_resources_api_create_experiment: Mock) -> None: """Test create() converts dict prompt_settings via PromptRunSettings roundtrip.""" # Given: a dict prompt_settings and a mocked API response @@ -285,8 +285,8 @@ def test_create_with_dict_prompt_settings(self, galileo_resources_api_create_exp assert actual_settings["model_alias"] == "GPT-4o" assert actual_settings["temperature"] == 0.8 - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_create_experiment_with_project_id( self, mock_get_with_env_fallbacks: Mock, galileo_resources_api_create_experiment: Mock ) -> None: @@ -312,8 +312,8 @@ def test_create_experiment_with_project_id( ) mock_get_with_env_fallbacks.assert_called_once_with(id=str(UUID(int=0)), name=None) - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_create_experiment_with_project_name( self, mock_get_with_env_fallbacks: Mock, galileo_resources_api_create_experiment: Mock ) -> None: @@ -339,8 +339,8 @@ def test_create_experiment_with_project_name( ) mock_get_with_env_fallbacks.assert_called_once_with(id=None, name="test_project") - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks", return_value=None) + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks", return_value=None) def test_create_experiment_without_project_fails( self, mock_get_with_env_fallbacks: Mock, galileo_resources_api_create_experiment: Mock ) -> None: @@ -361,8 +361,8 @@ def test_create_experiment_without_project_fails( with pytest.raises(ValueError, match="Project not specified and no defaults found"): create_experiment(experiment_name="test_experiment") - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_create_experiment_with_wrong_project_name_fails( self, mock_get_with_env_fallbacks: Mock, galileo_resources_api_create_experiment: Mock ) -> None: @@ -392,8 +392,8 @@ def test_create_experiment_empty_experiment_name_raises(self) -> None: with pytest.raises(ValueError, match="experiment_name is required"): create_experiment(experiment_name="", project_name="test_project") - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_with_project_id( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -404,8 +404,8 @@ def test_get_experiments_with_project_id( assert experiments[0].name == experiment_response().name list_experiments_mock.sync.assert_called_once_with(project_id=str(UUID(int=0)), client=ANY) - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_with_project_name( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -417,8 +417,8 @@ def test_get_experiments_with_project_name( list_experiments_mock.sync.assert_called_once_with(project_id=str(UUID(int=0)), client=ANY) mock_get_with_env_fallbacks.assert_called_once_with(id=None, name="test_project") - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_without_project_id_or_name_fails( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -428,8 +428,8 @@ def test_get_experiments_without_project_id_or_name_fails( with pytest.raises(ValueError, match="Project not specified and no defaults found"): get_experiments() - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_with_wrong_project_name_fails( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -439,8 +439,8 @@ def test_get_experiments_with_wrong_project_name_fails( with pytest.raises(ValueError, match="Project test_project does not exist"): get_experiments(project_name="test_project") - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiment_not_found(self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock) -> None: list_experiments_mock.sync = Mock(return_value=None) mock_get_with_env_fallbacks.return_value = project() @@ -457,8 +457,8 @@ def test_get_experiment_empty_experiment_name_raises(self) -> None: with pytest.raises(ValueError, match="experiment_name is required"): get_experiment(project_id=str(UUID(int=0)), experiment_name="") - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiment_neither_project_id_nor_name_raises( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -471,8 +471,8 @@ def test_get_experiment_neither_project_id_nor_name_raises( list_experiments_mock.sync.assert_not_called() - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiment_with_project_name( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -485,8 +485,8 @@ def test_get_experiment_with_project_name( list_experiments_mock.sync.assert_called_once_with(project_id=project().id, client=ANY) mock_get_with_env_fallbacks.assert_called_once_with(id=None, name="awesome-new-project") - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiment_with_wrong_project_name_fails( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -496,8 +496,8 @@ def test_get_experiment_with_wrong_project_name_fails( with pytest.raises(ValueError, match="Project awesome-new-project does not exist"): get_experiment(project_name="awesome-new-project", experiment_name=experiment_response().name) - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiment_with_project_id( self, mock_get_with_env_fallbacks: Mock, list_experiments_mock: Mock ) -> None: @@ -514,7 +514,7 @@ def test_get_experiment_with_project_id( ("dataset", "dataset_name", "dataset_id"), [("awesome-dataset", None, None), (None, "awesome-dataset", None), (None, None, "dataset_id")], ) - @patch.object(galileo.datasets.Datasets, "get") + @patch.object(splunk_ao.datasets.Datasets, "get") def test_load_dataset_and_records( self, mock_get_dataset, @@ -542,11 +542,11 @@ def test_load_dataset_and_records_error(self) -> None: load_dataset_and_records(dataset=None, dataset_name=None, dataset_id=None) assert str(exc_info.value) == "To load dataset records, dataset, dataset_name, or dataset_id must be provided" - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_project_name_loads_project( self, mock_get_project: Mock, @@ -564,11 +564,11 @@ def test_run_experiment_with_project_name_loads_project( mock_get_project.assert_called_once_with(id=None, name="awesome-new-project") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_project_id_loads_project( self, mock_get_project: Mock, @@ -589,11 +589,11 @@ def test_run_experiment_with_project_id_loads_project( mock_get_project.assert_called_once_with(id="awesome-new-project", name=None) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=None) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=None) def test_run_experiment_with_invalid_project_id_gives_error( self, mock_get_project: Mock, @@ -615,11 +615,11 @@ def test_run_experiment_with_invalid_project_id_gives_error( assert str(exc_info.value) == "Project with Id awesome-new-project does not exist" - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=None) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=None) def test_run_experiment_with_invalid_project_name_gives_error( self, mock_get_project: Mock, @@ -642,10 +642,10 @@ def test_run_experiment_with_invalid_project_name_gives_error( assert str(exc_info.value) == "Project awesome-new-project does not exist" @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_without_metrics( self, mock_get_project: Mock, @@ -676,11 +676,11 @@ def test_run_experiment_without_metrics( @pytest.mark.parametrize("console_url", ["http://fake.test:8088", "http://fake.test:8088/"]) @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_link_no_double_slash( self, mock_get_project: Mock, @@ -697,7 +697,7 @@ def test_run_experiment_link_no_double_slash( mock_config.console_url = console_url # When: running an experiment - with patch("galileo.experiments.SplunkAOConfig.get", return_value=mock_config): + with patch("splunk_ao.experiments.SplunkAOConfig.get", return_value=mock_config): result = run_experiment( "test_experiment", project="awesome-new-project", @@ -712,10 +712,10 @@ def test_run_experiment_link_no_double_slash( assert f"/project/{project().id}/experiments/{experiment_response().id}" in link @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_generated_output_flow( self, mock_get_project: Mock, @@ -743,10 +743,10 @@ def test_run_experiment_generated_output_flow( ) @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_prompt_takes_precedence_over_generated_output( self, mock_get_project: Mock, @@ -775,11 +775,11 @@ def test_run_experiment_prompt_takes_precedence_over_generated_output( prompt_settings=ANY, ) - @patch.object(galileo.datasets.Datasets, "get", return_value=None) - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get", return_value=None) + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_no_prompt_no_dataset_raises( self, mock_get_project: Mock, @@ -793,15 +793,15 @@ def test_run_experiment_no_prompt_no_dataset_raises( with pytest.raises(ValueError, match="dataset"): run_experiment("test_experiment", project="awesome-new-project") - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") @pytest.mark.parametrize("thread_pool", [True, False]) @pytest.mark.parametrize( ("function", "metrics", "num_spans", "span_type", "results", "aggregate_results"), @@ -952,12 +952,12 @@ def check_span(span: Span) -> int: assert num_spans == sum(check_span(span) for span in trace.spans) @travel(datetime(2012, 1, 1), tick=False) - @patch("galileo.utils.metrics.ScorerSettings") - @patch("galileo.utils.metrics.Scorers") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_w_prompt_template_and_metrics( self, mock_get_project: Mock, @@ -998,10 +998,10 @@ def test_run_experiment_w_prompt_template_and_metrics( mock_scorer_settings_class.return_value.create.assert_not_called() @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_w_prompt_template_and_prompt_settings( self, mock_get_project: Mock, @@ -1033,10 +1033,10 @@ def test_run_experiment_w_prompt_template_and_prompt_settings( ) @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_prompt_settings_as_dict( self, mock_get_with_env_fallbacks: Mock, @@ -1087,7 +1087,7 @@ def test_run_experiment_with_prompt_settings_as_dict( assert ps.presence_penalty == 0.0 assert ps.frequency_penalty == 0.0 - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") def test_experiments_create_with_prompt_settings_as_dict( self, galileo_resources_api_create_experiment: Mock ) -> None: @@ -1122,7 +1122,7 @@ def test_experiments_create_with_prompt_settings_as_dict( assert ps_dict["temperature"] == 0.5 assert ps_dict["max_tokens"] == 256 - @patch.object(galileo.experiments.Experiments, "create") + @patch.object(splunk_ao.experiments.Experiments, "create") def test_experiments_run_raises_when_create_raises(self, mock_create: Mock) -> None: # Given: Experiments.create raises mock_create.side_effect = RuntimeError("API unavailable") @@ -1131,13 +1131,13 @@ def test_experiments_run_raises_when_create_raises(self, mock_create: Mock) -> N with pytest.raises(RuntimeError, match="API unavailable"): Experiments().run( project_obj=project(), - dataset_obj=Mock(spec=galileo.datasets.Dataset), + dataset_obj=Mock(spec=splunk_ao.datasets.Dataset), experiment_name="test_experiment", prompt_template=None, scorers=None, ) - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) def test_experiments_run_with_prompt_settings_as_dict(self, mock_create: Mock) -> None: # Given: a project, dataset, and prompt_settings passed as a plain dict settings_dict = {"model_alias": "GPT-4o", "temperature": 0.5, "max_tokens": 256} @@ -1145,7 +1145,7 @@ def test_experiments_run_with_prompt_settings_as_dict(self, mock_create: Mock) - # When: Experiments().run() is called with prompt_settings as a plain dict Experiments().run( project_obj=project(), - dataset_obj=Mock(spec=galileo.datasets.Dataset), + dataset_obj=Mock(spec=splunk_ao.datasets.Dataset), experiment_name="test_experiment", prompt_template=prompt_template(), scorers=None, @@ -1162,14 +1162,14 @@ def test_experiments_run_with_prompt_settings_as_dict(self, mock_create: Mock) - assert ps.max_tokens == 256 @travel(datetime(2012, 1, 1), tick=False) - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_runner_and_dataset( self, mock_get_project: Mock, @@ -1228,10 +1228,10 @@ def runner(input) -> str: assert payload.traces[0].output == "Say hello: Which continent is Spain in?" @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create") - @patch.object(galileo.experiments.Experiments, "get") - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create") + @patch.object(splunk_ao.experiments.Experiments, "get") + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_raises_when_create_raises( self, mock_get_project: Mock, @@ -1253,14 +1253,14 @@ def test_run_experiment_raises_when_create_raises( ) @travel(datetime(2012, 1, 1), tick=False) - @patch.object(galileo.datasets.Datasets, "get") + @patch.object(splunk_ao.datasets.Datasets, "get") @patch.object( - galileo.experiments.Experiments, + splunk_ao.experiments.Experiments, "run", return_value={"experiment": experiment_response(), "link": "http://example.com", "message": "done"}, ) - @patch.object(galileo.experiments.Experiments, "get", return_value=None) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=None) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_on_error_warns_when_unused_in_prompt_template_flow( self, mock_get_project: Mock, @@ -1273,7 +1273,7 @@ def test_run_experiment_on_error_warns_when_unused_in_prompt_template_flow( on_error = Mock() # When: run_experiment() is called with a prompt template and on_error - with patch("galileo.experiments._logger") as mock_logger: + with patch("splunk_ao.experiments._logger") as mock_logger: run_experiment( "test_experiment", project="awesome-new-project", @@ -1289,13 +1289,13 @@ def test_run_experiment_on_error_warns_when_unused_in_prompt_template_flow( ) on_error.assert_not_called() - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_on_error_passed_to_flush_in_function_flow( self, mock_get_project: Mock, @@ -1319,7 +1319,7 @@ def test_run_experiment_on_error_passed_to_flush_in_function_flow( on_error = Mock() # When: run_experiment() is called with a function and on_error (function flow) - with patch("galileo.experiments.galileo_context.flush") as mock_flush: + with patch("splunk_ao.experiments.galileo_context.flush") as mock_flush: run_experiment( experiment_name="test_experiment", project="awesome-new-project", @@ -1332,7 +1332,7 @@ def test_run_experiment_on_error_passed_to_flush_in_function_flow( assert mock_flush.call_count >= 1 assert all(c == mock_call(on_error=on_error) for c in mock_flush.call_args_list) - @patch.object(galileo.datasets.Datasets, "get") + @patch.object(splunk_ao.datasets.Datasets, "get") def test_run_experiment_with_prompt_template_and_function( self, mock_get_dataset: Mock, dataset_content: DatasetContent ) -> None: @@ -1350,7 +1350,7 @@ def test_run_experiment_with_prompt_template_and_function( id="00000000-0000-0000-0000-000000000001", name=None, project_id=None, project_name=None ) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_prompt_template_and_local_dataset( self, mock_projects_client: Mock, local_dataset: list[dict[str, str]] ) -> None: @@ -1368,14 +1368,14 @@ def test_run_experiment_with_prompt_template_and_local_dataset( == "A dataset record, id, or name of a dataset must be provided when a prompt_template is used" ) - @patch("galileo.logger.logger.Projects") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.logger.logger.Projects") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_run_experiment_with_local_scorers_and_prompt_template( self, mock_scorer_settings_create: Mock, @@ -1408,8 +1408,8 @@ def test_run_experiment_with_local_scorers_and_prompt_template( == "Local metrics can only be used with a locally run experiment, not a prompt experiment." ) - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_create_scorer_configs(self, mock_scorer_settings_class, mock_scorers_class) -> None: # Setup mock return values — new code uses list_by_labels mock_scorers_instance = mock_scorers_class.return_value @@ -1420,7 +1420,7 @@ def test_create_scorer_configs(self, mock_scorer_settings_class, mock_scorers_cl mock_scorer_settings_class.return_value.create = MagicMock() # Test valid metrics - from galileo.utils.metrics import create_metric_configs + from splunk_ao.utils.metrics import create_metric_configs scorers, local_scorers = create_metric_configs( "project_id", "experiment_id", ["metric1", LocalMetricConfig(name="length", scorer_fn=lambda x: len(x))] @@ -1433,8 +1433,8 @@ def test_create_scorer_configs(self, mock_scorer_settings_class, mock_scorers_cl with pytest.raises(ValueError): create_metric_configs("project_id", "experiment_id", ["unknown_metric"]) - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_create_scorer_configs_with_metric_objects(self, mock_scorer_settings_class, mock_scorers_class) -> None: # Setup mock return values mock_scorers_instance = mock_scorers_class.return_value @@ -1454,12 +1454,12 @@ def test_create_scorer_configs_with_metric_objects(self, mock_scorer_settings_cl mock_version_response.to_dict.return_value = {"id": "version1", "version": 2} mock_scorers_instance.get_scorer_version.return_value = mock_version_response - from galileo.schema.metrics import Metric + from splunk_ao.schema.metrics import Metric # Test with Metric objects (without version) metric1 = Metric(name="metric1") metric2 = Metric(name="metric2") - from galileo.utils.metrics import create_metric_configs + from splunk_ao.utils.metrics import create_metric_configs scorers, local_scorers = create_metric_configs("project_id", "experiment_id", [metric1, metric2]) @@ -1472,7 +1472,7 @@ def test_create_scorer_configs_with_metric_objects(self, mock_scorer_settings_cl # Test with a Metric object with version versionable_metric = Metric(name="versionable_metric", version=2) - from galileo.utils.metrics import create_metric_configs + from splunk_ao.utils.metrics import create_metric_configs scorers, local_scorers = create_metric_configs("project_id", "experiment_id", [versionable_metric]) @@ -1485,7 +1485,7 @@ def test_create_scorer_configs_with_metric_objects(self, mock_scorer_settings_cl # Test mixed input types local_metric = LocalMetricConfig(name="length", scorer_fn=lambda x: len(x)) - from galileo.utils.metrics import create_metric_configs + from splunk_ao.utils.metrics import create_metric_configs scorers, local_scorers = create_metric_configs( "project_id", "experiment_id", ["metric1", local_metric, Metric(name="metric2")] @@ -1494,10 +1494,10 @@ def test_create_scorer_configs_with_metric_objects(self, mock_scorer_settings_cl assert len(scorers) == 2 # Should return two valid scorers assert len(local_scorers) == 1 # One local scorer - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", side_effect=ValueError("experiment creation failed")) - @patch.object(galileo.experiments.Experiments, "get", return_value=None) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", side_effect=ValueError("experiment creation failed")) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=None) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_job_creation_failure( self, mock_get_project: Mock, @@ -1521,12 +1521,12 @@ def test_run_experiment_job_creation_failure( mock_get_project.assert_called_once_with(id=None, name="awesome-new-project") - @patch("galileo.experiments.upsert_experiment_tag") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.jobs.Jobs, "create") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=None) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.experiments.upsert_experiment_tag") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.jobs.Jobs, "create") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=None) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_experiment_tags_basic( self, mock_get_project: Mock, @@ -1554,13 +1554,13 @@ def test_run_experiment_with_experiment_tags_basic( assert mock_upsert_tag.call_count == 3 - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_dataset_limit( self, mock_get_project: Mock, @@ -1601,12 +1601,12 @@ def test_run_experiment_with_dataset_limit( total_traces += len(payload.traces) assert total_traces == 150 - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_function_and_list_dataset( self, mock_get_project: Mock, @@ -1662,13 +1662,13 @@ def simple_function(input: dict) -> str: assert '{"input": "Which continent is Spain in?"}' in span_inputs[0] assert '{"input": "Which continent is Japan in?"}' in span_inputs[1] - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") - @patch.object(galileo.datasets.Datasets, "get") - @patch.object(galileo.experiments.Experiments, "create", return_value=experiment_response()) - @patch.object(galileo.experiments.Experiments, "get", return_value=experiment_response()) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") + @patch.object(splunk_ao.datasets.Datasets, "get") + @patch.object(splunk_ao.experiments.Experiments, "create", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=experiment_response()) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) def test_run_experiment_with_multi_page_pagination( self, mock_get_project: Mock, @@ -1859,13 +1859,13 @@ class TestExperimentGroups: """V1 experiment-group support: group-aware run/create + list_experiment_groups().""" @patch.object( - galileo.experiments.Experiments, + splunk_ao.experiments.Experiments, "run", return_value={"experiment": experiment_response(), "link": "x", "message": "y"}, ) - @patch.object(galileo.experiments.Experiments, "get", return_value=None) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) - @patch("galileo.experiments.load_dataset") + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=None) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.experiments.load_dataset") def test_run_experiment_with_experiment_group_name( self, load_dataset_mock: Mock, get_project_mock: Mock, get_experiment_mock: Mock, run_mock: Mock ) -> None: @@ -1889,13 +1889,13 @@ def test_run_experiment_with_experiment_group_name( assert "experiment_group_id" not in call_kwargs @patch.object( - galileo.experiments.Experiments, + splunk_ao.experiments.Experiments, "run", return_value={"experiment": experiment_response(), "link": "x", "message": "y"}, ) - @patch.object(galileo.experiments.Experiments, "get", return_value=None) - @patch.object(galileo.experiments.Projects, "get_with_env_fallbacks", return_value=project()) - @patch("galileo.experiments.load_dataset") + @patch.object(splunk_ao.experiments.Experiments, "get", return_value=None) + @patch.object(splunk_ao.experiments.Projects, "get_with_env_fallbacks", return_value=project()) + @patch("splunk_ao.experiments.load_dataset") def test_run_experiment_with_experiment_group_id( self, load_dataset_mock: Mock, get_project_mock: Mock, get_experiment_mock: Mock, run_mock: Mock ) -> None: @@ -1919,8 +1919,8 @@ def test_run_experiment_with_experiment_group_id( assert call_kwargs.get("experiment_group_id") == group_uuid assert "experiment_group_name" not in call_kwargs - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_create_experiment_with_experiment_group_name( self, get_project_mock: Mock, create_experiment_mock: Mock ) -> None: @@ -1939,8 +1939,8 @@ def test_create_experiment_with_experiment_group_name( assert body.additional_properties["experiment_group_name"] == "standalone-bench" assert "experiment_group_id" not in body.additional_properties - @patch("galileo.experiments.create_experiment_projects_project_id_experiments_post") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.create_experiment_projects_project_id_experiments_post") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_create_experiment_with_experiment_group_id( self, get_project_mock: Mock, create_experiment_mock: Mock ) -> None: @@ -1960,8 +1960,8 @@ def test_create_experiment_with_experiment_group_id( assert body.additional_properties["experiment_group_id"] == group_uuid assert "experiment_group_name" not in body.additional_properties - @patch("galileo.experiments.SplunkAOConfig") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.SplunkAOConfig") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_list_experiment_groups(self, get_project_mock: Mock, config_mock: Mock) -> None: """list_experiment_groups() POSTs to /experiment-groups/query and returns typed objects.""" # Given: a resolved project and a mocked httpx client returning two groups @@ -2023,8 +2023,8 @@ def test_list_experiment_groups(self, get_project_mock: Mock, config_mock: Mock) assert groups[0].experiment_count == 2 assert groups[1].is_system is True - @patch("galileo.experiments.SplunkAOConfig") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.SplunkAOConfig") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_list_experiment_groups_paginates_internally(self, get_project_mock: Mock, config_mock: Mock) -> None: """list_experiment_groups() walks all pages and returns the combined list.""" # Given: a project and an API that returns 2 pages @@ -2075,8 +2075,8 @@ def make_group(idx: int, system: bool = False) -> dict: assert len(groups) == 3 assert [g.name for g in groups] == ["group-1", "group-2", "group-3"] - @patch("galileo.experiments.SplunkAOConfig") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.SplunkAOConfig") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_with_group_name_filter(self, get_project_mock: Mock, config_mock: Mock) -> None: """get_experiments(experiment_group=...) calls the search endpoint with a name filter.""" # Given: a resolved project and a search endpoint that returns one matching experiment @@ -2111,8 +2111,8 @@ def test_get_experiments_with_group_name_filter(self, get_project_mock: Mock, co assert isinstance(result, list) assert len(result) == 1 - @patch("galileo.experiments.SplunkAOConfig") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.SplunkAOConfig") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_with_group_id_filter(self, get_project_mock: Mock, config_mock: Mock) -> None: """get_experiments(experiment_group_id=...) calls the search endpoint with an id filter.""" # Given: a resolved project and a search endpoint that returns one matching experiment @@ -2139,8 +2139,8 @@ def test_get_experiments_with_group_id_filter(self, get_project_mock: Mock, conf assert isinstance(result, list) assert len(result) == 1 - @patch("galileo.experiments.list_experiments_projects_project_id_experiments_get") - @patch("galileo.experiments.Projects.get_with_env_fallbacks") + @patch("splunk_ao.experiments.list_experiments_projects_project_id_experiments_get") + @patch("splunk_ao.experiments.Projects.get_with_env_fallbacks") def test_get_experiments_without_filter_unchanged( self, get_project_mock: Mock, list_experiments_mock: Mock ) -> None: diff --git a/tests/test_export.py b/tests/test_export.py index b92ecbde..3c84de36 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -5,8 +5,6 @@ import pytest -from galileo.export import export_records -from galileo.log_streams import LogStream from galileo.resources.errors import UnexpectedStatus from galileo.resources.models import ( LLMExportFormat, @@ -15,9 +13,11 @@ LogRecordsTextFilter, RootType, ) +from splunk_ao.export import export_records +from splunk_ao.log_streams import LogStream -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_basic(mock_export_records_stream): project_id = str(uuid4()) records_data = [ @@ -48,7 +48,7 @@ def test_export_records_basic(mock_export_records_stream): assert request_body.sort == sort -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_with_defaults(mock_export_records_stream): project_id = str(uuid4()) log_stream_id = str(uuid4()) @@ -64,8 +64,8 @@ def test_export_records_with_defaults(mock_export_records_stream): assert request_body.sort == LogRecordsSortClause(column_id="created_at", ascending=False) -@patch("galileo.export.LogStreams._list_all") -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.LogStreams._list_all") +@patch("splunk_ao.export.export_records_stream") def test_export_records_default_log_stream(mock_export_records_stream, mock_log_streams_list_all): project_id = str(uuid4()) oldest_log_stream_id = str(uuid4()) @@ -99,8 +99,8 @@ def test_export_records_default_log_stream(mock_export_records_stream, mock_log_ assert request_body.experiment_id is None -@patch("galileo.export.LogStreams._list_all") -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.LogStreams._list_all") +@patch("splunk_ao.export.export_records_stream") def test_export_records_no_default_log_stream(mock_export_records_stream, mock_log_streams_list_all): project_id = str(uuid4()) mock_log_streams_list_all.return_value = [] @@ -113,7 +113,7 @@ def test_export_records_no_default_log_stream(mock_export_records_stream, mock_l mock_export_records_stream.assert_not_called() -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_id_validation(mock_export_records_stream): project_id = str(uuid4()) log_stream_id = str(uuid4()) @@ -134,7 +134,7 @@ def test_export_records_id_validation(mock_export_records_stream): ) -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_with_filters(mock_export_records_stream): project_id = str(uuid4()) filters = [LogRecordsTextFilter(column_id="input", value="test", operator="eq")] @@ -155,7 +155,7 @@ def test_export_records_with_filters(mock_export_records_stream): assert request_body.filters == filters -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_api_failure(mock_export_records_stream): project_id = str(uuid4()) mock_export_records_stream.side_effect = UnexpectedStatus(400, b"Bad Request") @@ -173,7 +173,7 @@ def test_export_records_api_failure(mock_export_records_stream): @pytest.mark.parametrize("root_type", [RootType.TRACE, RootType.SPAN, RootType.SESSION]) -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_all_root_types(mock_export_records_stream, root_type): project_id = str(uuid4()) mock_export_records_stream.return_value = iter([]) @@ -193,7 +193,7 @@ def test_export_records_all_root_types(mock_export_records_stream, root_type): assert request_body.root_type == root_type -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_empty_response(mock_export_records_stream): project_id = str(uuid4()) mock_export_records_stream.return_value = iter([]) @@ -210,7 +210,7 @@ def test_export_records_empty_response(mock_export_records_stream): assert len(result) == 0 -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_malformed_json(mock_export_records_stream): project_id = str(uuid4()) lines = ['{"id": "123", "input": "test"}', "this is not json"] @@ -228,7 +228,7 @@ def test_export_records_malformed_json(mock_export_records_stream): ) -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_csv(mock_export_records_stream): project_id = str(uuid4()) csv_lines = ["id,input,output", "1,test1,out1", "2,test2,out2"] @@ -253,7 +253,7 @@ def test_export_records_csv(mock_export_records_stream): @pytest.mark.parametrize("redact_param", [True, False]) -@patch("galileo.export.export_records_stream") +@patch("splunk_ao.export.export_records_stream") def test_export_records_redact(mock_export_records_stream, redact_param): project_id = str(uuid4()) mock_export_records_stream.return_value = iter([]) diff --git a/tests/test_filter.py b/tests/test_filter.py index decc817c..d013594a 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -12,7 +12,7 @@ LogRecordsTextFilter, LogRecordsTextFilterOperator, ) -from galileo.shared.filter import ( +from splunk_ao.shared.filter import ( BooleanFilter, DateFilter, Filter, diff --git a/tests/test_galileo_context.py b/tests/test_galileo_context.py index f0166474..58d8df4f 100644 --- a/tests/test_galileo_context.py +++ b/tests/test_galileo_context.py @@ -2,8 +2,8 @@ import pytest -from galileo import galileo_context -from galileo.decorator import _experiment_id_context, _log_stream_context, _project_context +from splunk_ao import galileo_context +from splunk_ao.decorator import _experiment_id_context, _log_stream_context, _project_context from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -12,9 +12,9 @@ def reset_context() -> None: galileo_context.reset() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_nested_context_restoration( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: @@ -65,9 +65,9 @@ def test_nested_context_restoration( assert _experiment_id_context.get() is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_context_update_with_defaults( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, reset_context ) -> None: diff --git a/tests/test_integration.py b/tests/test_integration.py index 296e2341..7dc940a4 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -4,8 +4,11 @@ import pytest -from galileo.integration import Integration -from galileo.provider import ( +from galileo.resources.models.available_integrations import AvailableIntegrations +from galileo.resources.models.integration_db import IntegrationDB +from galileo.resources.models.integration_name import IntegrationName +from splunk_ao.integration import Integration +from splunk_ao.provider import ( AnthropicProvider, AzureProvider, BedrockProvider, @@ -13,10 +16,7 @@ Provider, UnconfiguredProvider, ) -from galileo.resources.models.available_integrations import AvailableIntegrations -from galileo.resources.models.integration_db import IntegrationDB -from galileo.resources.models.integration_name import IntegrationName -from galileo.shared.exceptions import IntegrationNotConfiguredError, ValidationError +from splunk_ao.shared.exceptions import IntegrationNotConfiguredError, ValidationError # Test data INTEGRATION_TYPES = [ @@ -52,8 +52,8 @@ def test_direct_init_raises_error(self): class TestIntegrationList: """Test Integration.list() methods.""" - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_available_integrations_integrations_available_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_available_integrations_integrations_available_get") def test_list_all_returns_strings(self, mock_available, mock_config): """list(all=True) returns list of string type names.""" mock_response = MagicMock(spec=AvailableIntegrations) @@ -68,8 +68,8 @@ def test_list_all_returns_strings(self, mock_available, mock_config): assert "anthropic" in result assert "azure" in result - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_list_returns_providers(self, mock_list, mock_config): """list() returns Provider objects.""" mock_list.sync.return_value = [ @@ -87,8 +87,8 @@ def test_list_returns_providers(self, mock_list, mock_config): assert result[1].name == "anthropic" assert result[1].is_selected is False - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_list_empty_returns_empty_list(self, mock_list, mock_config): """list() returns empty list when no integrations.""" mock_list.sync.return_value = [] @@ -97,8 +97,8 @@ def test_list_empty_returns_empty_list(self, mock_list, mock_config): assert result == [] - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") @pytest.mark.parametrize("name,enum_name,provider_class", INTEGRATION_TYPES) def test_list_creates_correct_provider_type(self, mock_list, mock_config, name, enum_name, provider_class): """list() creates correct Provider subclass for each type.""" @@ -114,8 +114,8 @@ def test_list_creates_correct_provider_type(self, mock_list, mock_config, name, class TestIntegrationRefresh: """Test Integration.refresh() method.""" - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_refresh_updates_attributes(self, mock_list, mock_config): """refresh() updates integration attributes from API.""" mock_integration = create_mock_integration(IntegrationName.OPENAI) @@ -144,8 +144,8 @@ def test_refresh_without_id_raises_error(self): class TestIntegrationConvenienceProperties: """Test Integration convenience properties (openai, azure, etc).""" - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_property_returns_configured_integration(self, mock_list, mock_config): """Integration.openai returns OpenAI provider if configured.""" mock_list.sync.return_value = [create_mock_integration(IntegrationName.OPENAI)] @@ -155,8 +155,8 @@ def test_property_returns_configured_integration(self, mock_list, mock_config): assert isinstance(result, OpenAIProvider) assert result.name == "openai" - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_property_returns_unconfigured_provider_when_not_configured(self, mock_list, mock_config): """Integration.azure returns UnconfiguredProvider if not configured.""" mock_list.sync.return_value = [] @@ -165,8 +165,8 @@ def test_property_returns_unconfigured_provider_when_not_configured(self, mock_l assert isinstance(result, UnconfiguredProvider) - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_property_prefers_selected_integration(self, mock_list, mock_config): """Property returns selected integration when multiple exist.""" mock1 = create_mock_integration(IntegrationName.OPENAI, is_selected=False) @@ -182,8 +182,8 @@ def test_property_prefers_selected_integration(self, mock_list, mock_config): class TestIntegrationFactoryMethods: """Test Integration factory methods.""" - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.create_or_update_integration_integrations_openai_put") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.create_or_update_integration_integrations_openai_put") def test_create_openai_returns_provider(self, mock_create, mock_config): """create_openai() returns OpenAIProvider.""" mock_response = create_mock_integration(IntegrationName.OPENAI) @@ -194,8 +194,8 @@ def test_create_openai_returns_provider(self, mock_create, mock_config): assert isinstance(result, OpenAIProvider) assert result.id == str(mock_response.id) - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.create_or_update_integration_integrations_azure_put") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.create_or_update_integration_integrations_azure_put") def test_create_azure_returns_provider(self, mock_create, mock_config): """create_azure() returns AzureProvider.""" mock_response = create_mock_integration(IntegrationName.AZURE) @@ -206,8 +206,8 @@ def test_create_azure_returns_provider(self, mock_create, mock_config): assert isinstance(result, AzureProvider) assert result.id == str(mock_response.id) - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.create_or_update_integration_integrations_aws_bedrock_put") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.create_or_update_integration_integrations_aws_bedrock_put") def test_create_bedrock_returns_provider(self, mock_create, mock_config): """create_bedrock() returns BedrockProvider.""" mock_response = create_mock_integration(IntegrationName.AWS_BEDROCK) @@ -218,8 +218,8 @@ def test_create_bedrock_returns_provider(self, mock_create, mock_config): assert isinstance(result, BedrockProvider) assert result.id == str(mock_response.id) - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.create_or_update_integration_integrations_anthropic_put") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.create_or_update_integration_integrations_anthropic_put") def test_create_anthropic_returns_provider(self, mock_create, mock_config): """create_anthropic() returns AnthropicProvider.""" mock_response = create_mock_integration(IntegrationName.ANTHROPIC) @@ -322,8 +322,8 @@ def test_repr_and_str_show_integration_name(self, integration_name): assert "UnconfiguredProvider" in repr(provider) assert integration_name in str(provider) - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_integration_property_returns_unconfigured_provider(self, mock_list, mock_config): """Integration properties return UnconfiguredProvider when not configured.""" mock_list.sync.return_value = [] @@ -334,8 +334,8 @@ def test_integration_property_returns_unconfigured_provider(self, mock_list, moc assert isinstance(Integration.bedrock, UnconfiguredProvider) assert isinstance(Integration.anthropic, UnconfiguredProvider) - @patch("galileo.integration.SplunkAOConfig.get") - @patch("galileo.integration.list_integrations_integrations_get") + @patch("splunk_ao.integration.SplunkAOConfig.get") + @patch("splunk_ao.integration.list_integrations_integrations_get") def test_unconfigured_provider_works_with_if_statement(self, mock_list, mock_config): """UnconfiguredProvider works correctly in if statements.""" mock_list.sync.return_value = [] @@ -356,8 +356,8 @@ def test_unconfigured_provider_works_with_if_statement(self, mock_list, mock_con class TestProviderModels: """Test Provider.models property.""" - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.get_available_models_llm_integrations_llm_integration_models_get") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.get_available_models_llm_integrations_llm_integration_models_get") def test_models_returns_model_list(self, mock_get_models, mock_config): """models property returns list of Model objects.""" # Create a synced provider @@ -380,8 +380,8 @@ def test_models_returns_model_list(self, mock_get_models, mock_config): assert models[0].provider_name == "openai" assert str(models[0]) == "gpt-4o" - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.get_available_models_llm_integrations_llm_integration_models_get") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.get_available_models_llm_integrations_llm_integration_models_get") def test_models_raises_error_when_not_synced(self, mock_get_models, mock_config): """models property raises ValidationError when provider not synced.""" # Create a non-synced provider @@ -391,8 +391,8 @@ def test_models_raises_error_when_not_synced(self, mock_get_models, mock_config) with pytest.raises(ValidationError, match="Cannot get models for provider without syncing"): _ = provider.models - @patch("galileo.provider.SplunkAOConfig.get") - @patch("galileo.provider.get_available_models_llm_integrations_llm_integration_models_get") + @patch("splunk_ao.provider.SplunkAOConfig.get") + @patch("splunk_ao.provider.get_available_models_llm_integrations_llm_integration_models_get") def test_models_works_for_different_provider_types(self, mock_get_models, mock_config): """models property works for different provider types.""" # Test multiple provider types diff --git a/tests/test_job_progress.py b/tests/test_job_progress.py index 00376c48..61c7a785 100644 --- a/tests/test_job_progress.py +++ b/tests/test_job_progress.py @@ -6,9 +6,9 @@ import pytest from pytest import CaptureFixture, LogCaptureFixture -from galileo.job_progress import job_progress, scorer_jobs_status from galileo.resources.models import HTTPValidationError, JobDB, ValidationError from galileo_core.constants.job import JobStatus +from splunk_ao.job_progress import job_progress, scorer_jobs_status FIXED_PROJECT_ID = str(uuid4()) FIXED_RUN_ID = str(uuid4()) @@ -47,8 +47,8 @@ def _job_db_factory( class TestJobProgress: - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") - @patch("galileo.job_progress.get_job_jobs_job_id_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_job_jobs_job_id_get.sync") def test_completed(self, mock_get_job: Mock, mock_get_scorer_jobs: Mock): mock_get_job.return_value = _job_db_factory(status=JobStatus.completed) mock_get_scorer_jobs.return_value = [] @@ -56,7 +56,7 @@ def test_completed(self, mock_get_job: Mock, mock_get_scorer_jobs: Mock): job_progress(job_id=FIXED_JOB_ID, project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) mock_get_job.assert_called_with(client=ANY, job_id=FIXED_JOB_ID) - @patch("galileo.job_progress.get_job_jobs_job_id_get.sync") + @patch("splunk_ao.job_progress.get_job_jobs_job_id_get.sync") def test_failed(self, mock_get_job: Mock): mock_get_job.return_value = _job_db_factory(status=JobStatus.failed, error_message="Test error") @@ -64,7 +64,7 @@ def test_failed(self, mock_get_job: Mock): job_progress(job_id=FIXED_JOB_ID, project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) mock_get_job.assert_called_with(client=ANY, job_id=FIXED_JOB_ID) - @patch("galileo.job_progress.get_job_jobs_job_id_get.sync") + @patch("splunk_ao.job_progress.get_job_jobs_job_id_get.sync") def test_get_job_fails(self, mock_get_job: Mock): mock_get_job.return_value = None @@ -72,7 +72,7 @@ def test_get_job_fails(self, mock_get_job: Mock): job_progress(job_id=FIXED_JOB_ID, project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) mock_get_job.assert_called_with(client=ANY, job_id=FIXED_JOB_ID) - @patch("galileo.job_progress.get_job_jobs_job_id_get.sync") + @patch("splunk_ao.job_progress.get_job_jobs_job_id_get.sync") def test_get_job_http_validation_error(self, mock_get_job: Mock): detail = [ValidationError(loc=["path", "job_id"], msg="value is not a valid uuid", type_="type_error.uuid")] mock_get_job.return_value = HTTPValidationError(detail=detail) @@ -82,7 +82,7 @@ def test_get_job_http_validation_error(self, mock_get_job: Mock): class TestScorerJobsStatus: - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_simple(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enable_galileo_logging): mock_get_jobs.return_value = [ _job_db_factory( @@ -92,11 +92,11 @@ def test_simple(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enable_gal ) ] - with caplog.at_level(logging.INFO, logger="galileo.job_progress"): + with caplog.at_level(logging.INFO, logger="splunk_ao.job_progress"): scorer_jobs_status(project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) assert "pii: Computing 🚧" in caplog.text - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_skips_prompt_run(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enable_galileo_logging): mock_get_jobs.return_value = [ _job_db_factory(job_name="log_stream_run"), @@ -107,11 +107,11 @@ def test_skips_prompt_run(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, ), ] - with caplog.at_level(logging.INFO, logger="galileo.job_progress"): + with caplog.at_level(logging.INFO, logger="splunk_ao.job_progress"): scorer_jobs_status(project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) assert "pii: Computing 🚧" in caplog.text - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_no_scorer_jobs(self, mock_get_jobs: Mock, capsys: CaptureFixture[str]): mock_get_jobs.return_value = [_job_db_factory(job_name="log_stream_run")] @@ -119,7 +119,7 @@ def test_no_scorer_jobs(self, mock_get_jobs: Mock, capsys: CaptureFixture[str]): captured = capsys.readouterr() assert captured.out == "" - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_one_of_each(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enable_galileo_logging): mock_get_jobs.return_value = [ _job_db_factory(job_name="log_stream_run"), @@ -141,13 +141,13 @@ def test_one_of_each(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enabl ), ] - with caplog.at_level(logging.INFO, logger="galileo.job_progress"): + with caplog.at_level(logging.INFO, logger="splunk_ao.job_progress"): scorer_jobs_status(project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) assert "pii: Computing 🚧" in caplog.text assert "toxicity: Failed ❌, error was: An error occurred." in caplog.text assert "chunk_attribution_utilization_plus: Done ✅" in caplog.text - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_unknown_scorer_name(self, mock_get_jobs: Mock, caplog: LogCaptureFixture, enable_galileo_logging): mock_get_jobs.return_value = [ _job_db_factory(job_name="log_stream_run"), @@ -158,11 +158,11 @@ def test_unknown_scorer_name(self, mock_get_jobs: Mock, caplog: LogCaptureFixtur ), ] - with caplog.at_level(logging.INFO, logger="galileo.job_progress"): + with caplog.at_level(logging.INFO, logger="splunk_ao.job_progress"): scorer_jobs_status(project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) assert "abc: Computing 🚧" in caplog.text - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_get_run_scorer_jobs_fails(self, mock_get_jobs: Mock): mock_get_jobs.return_value = None @@ -171,7 +171,7 @@ def test_get_run_scorer_jobs_fails(self, mock_get_jobs: Mock): ): scorer_jobs_status(project_id=FIXED_PROJECT_ID, run_id=FIXED_RUN_ID) - @patch("galileo.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") + @patch("splunk_ao.job_progress.get_jobs_for_project_run_projects_project_id_runs_run_id_jobs_get.sync") def test_get_run_scorer_jobs_http_validation_error(self, mock_get_jobs: Mock): detail = [ValidationError(loc=["path", "project_id"], msg="value is not a valid uuid", type_="type_error.uuid")] mock_get_jobs.return_value = HTTPValidationError(detail=detail) diff --git a/tests/test_jobs.py b/tests/test_jobs.py index 91ba40e3..4425dd8a 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -3,9 +3,9 @@ import pytest -from galileo.jobs import Jobs from galileo.resources.models import HTTPValidationError, PromptRunSettings, TaskType, ValidationError from galileo.resources.types import Response +from splunk_ao.jobs import Jobs def _make_422_response(msg: str = "Invalid model alias: 'gpt-4o-mini'") -> Response: @@ -34,7 +34,7 @@ def _make_job_kwargs(**overrides): class TestJobsCreate: - @patch("galileo.jobs.create_job_jobs_post") + @patch("splunk_ao.jobs.create_job_jobs_post") def test_raises_value_error_with_clear_message_on_invalid_model_alias(self, mock_post: MagicMock) -> None: """Jobs.create() with invalid model_alias (HTTP 422) raises ValueError with readable message.""" # Given: the API returns a 422 with validation error for model_alias @@ -44,7 +44,7 @@ def test_raises_value_error_with_clear_message_on_invalid_model_alias(self, mock with pytest.raises(ValueError, match="Request validation failed"): Jobs().create(**_make_job_kwargs()) - @patch("galileo.jobs.create_job_jobs_post") + @patch("splunk_ao.jobs.create_job_jobs_post") def test_error_message_contains_field_path_and_backend_message(self, mock_post: MagicMock) -> None: """The ValueError includes the field path and backend error message.""" # Given: the API returns a 422 with specific validation detail @@ -57,7 +57,7 @@ def test_error_message_contains_field_path_and_backend_message(self, mock_post: assert "model_alias" in msg assert "gpt-4o-mini" in msg - @patch("galileo.jobs.create_job_jobs_post") + @patch("splunk_ao.jobs.create_job_jobs_post") def test_does_not_raise_galileo_http_exception(self, mock_post: MagicMock) -> None: """Jobs.create() no longer raises the empty GalileoHTTPException on 422.""" # Given: the API returns a 422 response @@ -76,7 +76,7 @@ def test_does_not_raise_galileo_http_exception(self, mock_post: MagicMock) -> No except ValueError: pass # expected - @patch("galileo.jobs.create_job_jobs_post") + @patch("splunk_ao.jobs.create_job_jobs_post") def test_raises_value_error_on_unexpected_non_200(self, mock_post: MagicMock) -> None: """Jobs.create() raises ValueError with status code for non-422 unexpected responses.""" # Given: the API returns an unexpected non-200 response with no parsed body @@ -88,7 +88,7 @@ def test_raises_value_error_on_unexpected_non_200(self, mock_post: MagicMock) -> with pytest.raises(ValueError, match="503"): Jobs().create(**_make_job_kwargs()) - @patch("galileo.jobs.create_job_jobs_post") + @patch("splunk_ao.jobs.create_job_jobs_post") def test_raises_value_error_when_api_returns_string_detail(self, mock_post: MagicMock) -> None: """Jobs.create() surfaces the API message when the 422 detail is a plain string.""" # Given: the API returns a 422 whose 'detail' is a plain string (not the standard list shape) diff --git a/tests/test_langchain.py b/tests/test_langchain.py index 3ce4c9a5..c69e079c 100644 --- a/tests/test_langchain.py +++ b/tests/test_langchain.py @@ -10,23 +10,23 @@ from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage from langchain_core.outputs import ChatGeneration, LLMResult -from galileo import Message, MessageRole, galileo_context -from galileo.config import SplunkAOConfig -from galileo.handlers.langchain import SplunkAOAsyncCallback, SplunkAOCallback -from galileo.handlers.langchain.utils import parse_llm_result, update_root_to_agent -from galileo.logger.logger import SplunkAOLogger -from galileo.schema.handlers import Node -from galileo.utils.singleton import SplunkAOLoggerSingleton -from galileo.utils.uuid_utils import uuid7_to_uuid4 from galileo_core.schemas.shared.document import Document as GalileoDocument +from splunk_ao import Message, MessageRole, galileo_context +from splunk_ao.config import SplunkAOConfig +from splunk_ao.handlers.langchain import SplunkAOAsyncCallback, SplunkAOCallback +from splunk_ao.handlers.langchain.utils import parse_llm_result, update_root_to_agent +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.schema.handlers import Node +from splunk_ao.utils.singleton import SplunkAOLoggerSingleton +from splunk_ao.utils.uuid_utils import uuid7_to_uuid4 from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client class TestSplunkAOCallback: @pytest.fixture - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def galileo_logger(self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock): """Creates a mock Galileo logger for testing""" setup_mock_traces_client(mock_traces_client) @@ -232,7 +232,9 @@ def test_on_chat_model_start(self, callback: SplunkAOCallback) -> None: assert input_data[1]["role"] == "user" assert input_data[2]["role"] == "assistant" - def test_on_chat_model_start_end_with_tools(self, callback: SplunkAOCallback, galileo_logger: SplunkAOLogger) -> None: + def test_on_chat_model_start_end_with_tools( + self, callback: SplunkAOCallback, galileo_logger: SplunkAOLogger + ) -> None: """Test chat model start and end callbacks with tools""" run_id = uuid.uuid4() chain_id = uuid.uuid4() @@ -1021,9 +1023,9 @@ class TestSplunkAOCallbackWithIngestionHook: @pytest.fixture(autouse=True) def logger_mocks(self): with ( - patch("galileo.logger.logger.LogStreams") as mock_logstreams, - patch("galileo.logger.logger.Projects") as mock_projects, - patch("galileo.logger.logger.Traces") as mock_traces, + patch("splunk_ao.logger.logger.LogStreams") as mock_logstreams, + patch("splunk_ao.logger.logger.Projects") as mock_projects, + patch("splunk_ao.logger.logger.Traces") as mock_traces, ): setup_mock_traces_client(mock_traces) setup_mock_projects_client(mock_projects) diff --git a/tests/test_langchain_async.py b/tests/test_langchain_async.py index 8599c442..1891e7e6 100644 --- a/tests/test_langchain_async.py +++ b/tests/test_langchain_async.py @@ -11,19 +11,19 @@ from langchain_core.outputs import ChatGeneration, LLMResult from pytest import mark -from galileo import Message, MessageRole -from galileo.handlers.langchain import SplunkAOAsyncCallback -from galileo.logger.logger import SplunkAOLogger -from galileo.utils.uuid_utils import uuid7_to_uuid4 from galileo_core.schemas.shared.document import Document as GalileoDocument +from splunk_ao import Message, MessageRole +from splunk_ao.handlers.langchain import SplunkAOAsyncCallback +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.utils.uuid_utils import uuid7_to_uuid4 from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client class TestSplunkAOAsyncCallback: @pytest.fixture - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def galileo_logger(self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock): """Creates a mock Galileo logger for testing""" setup_mock_traces_client(mock_traces_client) @@ -499,7 +499,9 @@ async def test_extracting_chain_names_from_metadata( assert traces[0].spans[0].spans[0].name == "Test Chain 2" @mark.asyncio - async def test_complex_execution_flow(self, callback: SplunkAOAsyncCallback, galileo_logger: SplunkAOLogger) -> None: + async def test_complex_execution_flow( + self, callback: SplunkAOAsyncCallback, galileo_logger: SplunkAOLogger + ) -> None: """Test a complex execution flow with multiple component types""" # Create UUIDs for different components chain_id = uuid.uuid4() @@ -841,7 +843,9 @@ async def test_step_number_propagation( assert root_span.step_number == step_number @mark.asyncio - async def test_on_nested_agent_chains(self, callback: SplunkAOAsyncCallback, galileo_logger: SplunkAOLogger) -> None: + async def test_on_nested_agent_chains( + self, callback: SplunkAOAsyncCallback, galileo_logger: SplunkAOLogger + ) -> None: """Test nested agent chain handling and name change""" outer_run_id = uuid.uuid4() inner_run_id = uuid.uuid4() diff --git a/tests/test_langchain_middleware.py b/tests/test_langchain_middleware.py index 1b08de76..5d3b915b 100644 --- a/tests/test_langchain_middleware.py +++ b/tests/test_langchain_middleware.py @@ -8,9 +8,9 @@ from langgraph.runtime import Runtime from pydantic import BaseModel -from galileo import galileo_context -from galileo.handlers.langchain.middleware import SplunkAOMiddleware -from galileo.logger.logger import SplunkAOLogger +from splunk_ao import galileo_context +from splunk_ao.handlers.langchain.middleware import SplunkAOMiddleware +from splunk_ao.logger.logger import SplunkAOLogger from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -88,9 +88,9 @@ class RealArgsSchema(BaseModel): @pytest.fixture -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def galileo_logger(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock): """Creates a mock Galileo logger for testing.""" setup_mock_traces_client(mock_traces_client) @@ -494,9 +494,9 @@ class TestIngestionHook: @pytest.fixture(autouse=True) def logger_mocks(self): with ( - patch("galileo.logger.logger.LogStreams") as mock_logstreams, - patch("galileo.logger.logger.Projects") as mock_projects, - patch("galileo.logger.logger.Traces") as mock_traces, + patch("splunk_ao.logger.logger.LogStreams") as mock_logstreams, + patch("splunk_ao.logger.logger.Projects") as mock_projects, + patch("splunk_ao.logger.logger.Traces") as mock_traces, ): setup_mock_traces_client(mock_traces) setup_mock_projects_client(mock_projects) diff --git a/tests/test_log_stream.py b/tests/test_log_stream.py index cdcb895d..92922485 100644 --- a/tests/test_log_stream.py +++ b/tests/test_log_stream.py @@ -3,17 +3,17 @@ import pytest -from galileo.exceptions import NotFoundError -from galileo.log_stream import LogStream -from galileo.projects import ProjectNotFoundError, ProjectsAPIException from galileo.resources.models import LLMExportFormat, LogRecordsSortClause, RootType from galileo.resources.models.log_records_column_info import LogRecordsColumnInfo from galileo.resources.models.step_type import StepType -from galileo.search import RecordType -from galileo.shared.base import SyncState -from galileo.shared.column import ColumnCollection -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError -from galileo.shared.query_result import QueryResult +from splunk_ao.exceptions import NotFoundError +from splunk_ao.log_stream import LogStream +from splunk_ao.projects import ProjectNotFoundError, ProjectsAPIException +from splunk_ao.search import RecordType +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.column import ColumnCollection +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError +from splunk_ao.shared.query_result import QueryResult class TestLogStreamInitialization: @@ -65,8 +65,8 @@ def test_init_with_both_project_id_and_name_succeeds(self, reset_configuration: class TestLogStreamCreate: """Test suite for LogStream.create() method.""" - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_persists_log_stream_to_api_with_project_id( self, mock_projects_class: MagicMock, @@ -95,8 +95,8 @@ def test_create_persists_log_stream_to_api_with_project_id( assert log_stream.id == mock_logstream.id assert log_stream.is_synced() - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_persists_log_stream_to_api_with_project_name( self, mock_projects_class: MagicMock, @@ -128,8 +128,8 @@ def test_create_persists_log_stream_to_api_with_project_name( assert log_stream.is_synced() assert log_stream.project_name == "Test Project" - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_handles_api_failure( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -154,7 +154,7 @@ def test_create_handles_api_failure( assert log_stream.sync_state == SyncState.FAILED_SYNC - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_names_project_in_error_when_project_name_not_found( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -171,7 +171,7 @@ def test_create_names_project_in_error_when_project_name_not_found( with pytest.raises(NotFoundError, match=r'Project "my-nonexistent-project" not found'): log_stream.create() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_without_project_info_raises_error( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -196,8 +196,8 @@ def test_create_without_project_info_raises_error( class TestLogStreamGet: """Test suite for LogStream.get() class method.""" - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_returns_log_stream_with_project_id( self, mock_projects_class: MagicMock, @@ -227,8 +227,8 @@ def test_get_returns_log_stream_with_project_id( assert log_stream.project_name == "Test Project" mock_service.get.assert_called_once_with(name="Test Stream", project_id="test-project-id") - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_returns_log_stream_with_project_name( self, mock_projects_class: MagicMock, @@ -258,8 +258,8 @@ def test_get_returns_log_stream_with_project_name( assert log_stream.project_name == "Test Project" mock_service.get.assert_called_once_with(name="Test Stream", project_id="resolved-project-id") - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_returns_none_when_not_found( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -282,7 +282,7 @@ def test_get_returns_none_when_not_found( # Then: None is returned assert log_stream is None - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_raises_error_without_project_info_and_no_env_fallback( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -296,7 +296,7 @@ def test_get_raises_error_without_project_info_and_no_env_fallback( with pytest.raises(NotFoundError, match="No project specified"): LogStream.get(name="Test Stream") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_raises_not_found_when_project_id_unknown( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -310,7 +310,7 @@ def test_get_raises_not_found_when_project_id_unknown( with pytest.raises(NotFoundError, match=r'Project with id "unknown-id" not found'): LogStream.get(name="Test Stream", project_id="unknown-id") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_reraises_non_404_projects_api_exception( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -324,8 +324,8 @@ def test_get_reraises_non_404_projects_api_exception( with pytest.raises(ProjectsAPIException): LogStream.get(name="Test Stream", project_id="some-id") - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_get_uses_env_fallback_when_no_project_specified( self, mock_projects_class: MagicMock, @@ -359,8 +359,8 @@ def test_get_uses_env_fallback_when_no_project_specified( class TestLogStreamList: """Test suite for LogStream.list() class method.""" - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_returns_all_log_streams_with_project_id( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -400,8 +400,8 @@ def test_list_returns_all_log_streams_with_project_id( assert all(ls.project_name == "Test Project" for ls in log_streams) mock_service.list.assert_called_once_with(project_id="test-project-id", limit=100, starting_token=0) - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_returns_all_log_streams_with_project_name( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -434,7 +434,7 @@ def test_list_returns_all_log_streams_with_project_name( assert all(ls.project_name == "Test Project" for ls in log_streams) mock_service.list.assert_called_once_with(project_id="resolved-project-id", limit=100, starting_token=0) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_raises_error_without_project_info_and_no_env_fallback( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -448,7 +448,7 @@ def test_list_raises_error_without_project_info_and_no_env_fallback( with pytest.raises(NotFoundError, match="No project specified"): LogStream.list() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_raises_not_found_when_project_id_unknown( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -462,7 +462,7 @@ def test_list_raises_not_found_when_project_id_unknown( with pytest.raises(NotFoundError, match=r'Project with id "unknown-id" not found'): LogStream.list(project_id="unknown-id") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_reraises_non_404_projects_api_exception( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -476,8 +476,8 @@ def test_list_reraises_non_404_projects_api_exception( with pytest.raises(ProjectsAPIException): LogStream.list(project_id="some-id") - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_forwards_limit_to_service( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -500,8 +500,8 @@ def test_list_forwards_limit_to_service( # Then: limit is forwarded to the service call mock_service.list.assert_called_once_with(project_id="test-project-id", limit=3, starting_token=0) - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_forwards_starting_token_to_service( self, mock_projects_class: MagicMock, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -524,8 +524,8 @@ def test_list_forwards_starting_token_to_service( # Then: starting_token is forwarded to the service call mock_service.list.assert_called_once_with(project_id="test-project-id", limit=100, starting_token=100) - @patch("galileo.log_stream.LogStreams") - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") def test_list_uses_env_fallback_when_no_project_specified( self, mock_projects_class: MagicMock, @@ -558,8 +558,8 @@ def test_list_uses_env_fallback_when_no_project_specified( class TestLogStreamRefresh: """Test suite for LogStream.refresh() method.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") def test_refresh_updates_attributes_from_api( self, mock_logstreams_class: MagicMock, @@ -609,8 +609,8 @@ def test_refresh_raises_error_for_local_only(self, reset_configuration: None) -> with pytest.raises(ValueError, match="Log stream ID is not set"): log_stream.refresh() - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.LogStreams") def test_refresh_raises_error_if_log_stream_no_longer_exists( self, mock_logstreams_class: MagicMock, @@ -632,7 +632,7 @@ def test_refresh_raises_error_if_log_stream_no_longer_exists( assert log_stream.sync_state == SyncState.FAILED_SYNC - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.log_stream.LogStreams") def test_refresh_without_project_id_raises_error( self, mock_logstreams_class: MagicMock, reset_configuration: None, mock_logstream: MagicMock ) -> None: @@ -662,9 +662,9 @@ class TestLogStreamQuery: ("get_sessions", RecordType.SESSION, 10), ], ) - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.Search") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.Search") + @patch("splunk_ao.log_stream.LogStreams") def test_query_methods( self, mock_logstreams_class: MagicMock, @@ -717,7 +717,7 @@ def test_query_raises_error_for_local_only(self, reset_configuration: None) -> N with pytest.raises(ValueError, match="Log stream ID is not set"): log_stream.query(record_type=RecordType.SPAN) - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.log_stream.LogStreams") def test_query_raises_error_without_project_id( self, mock_logstreams_class: MagicMock, reset_configuration: None, mock_logstream: MagicMock ) -> None: @@ -736,9 +736,9 @@ def test_query_raises_error_without_project_id( class TestLogStreamExportRecords: """Test suite for LogStream.export_records() method.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.ExportClient") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.ExportClient") + @patch("splunk_ao.log_stream.LogStreams") def test_export_records_with_default_params( self, mock_logstreams_class: MagicMock, @@ -775,9 +775,9 @@ def test_export_records_with_default_params( ) assert result == mock_iterator - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.ExportClient") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.ExportClient") + @patch("splunk_ao.log_stream.LogStreams") def test_export_records_with_custom_params( self, mock_logstreams_class: MagicMock, @@ -827,7 +827,7 @@ def test_export_records_raises_error_for_local_only(self, reset_configuration: N with pytest.raises(ValueError, match="Log stream ID is not set"): log_stream.export_records() - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.log_stream.LogStreams") def test_export_records_raises_error_without_project_id( self, mock_logstreams_class: MagicMock, reset_configuration: None ) -> None: @@ -846,9 +846,9 @@ def test_export_records_raises_error_without_project_id( class TestLogStreamContext: """Test suite for LogStream.context() method.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.galileo_context") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.galileo_context") + @patch("splunk_ao.log_stream.LogStreams") def test_context_returns_galileo_context( self, mock_logstreams_class: MagicMock, @@ -868,7 +868,7 @@ def test_context_returns_galileo_context( mock_galileo_context.return_value = mock_context # Mock the project property - with patch("galileo.log_stream.Project") as mock_project_class: + with patch("splunk_ao.log_stream.Project") as mock_project_class: mock_project = MagicMock() mock_project.name = "Test Project" mock_project_class.get.return_value = mock_project @@ -883,9 +883,9 @@ def test_context_returns_galileo_context( class TestLogStreamProject: """Test suite for LogStream.project property.""" - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.Project") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.Project") + @patch("splunk_ao.log_stream.LogStreams") def test_project_property_returns_project( self, mock_logstreams_class: MagicMock, @@ -936,9 +936,9 @@ class TestLogStreamColumns: ), ], ) - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.SplunkAOConfig") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.SplunkAOConfig") + @patch("splunk_ao.log_stream.LogStreams") def test_column_properties_return_column_collection( self, mock_logstreams_class: MagicMock, @@ -972,7 +972,7 @@ def test_column_properties_return_column_collection( mock_response = MagicMock() mock_response.columns = [mock_column_1, mock_column_2] - with patch(f"galileo.log_stream.{api_func_name}") as mock_api_func: + with patch(f"splunk_ao.log_stream.{api_func_name}") as mock_api_func: mock_api_func.sync.return_value = mock_response log_stream = LogStream.get(name="Test Stream", project_id="test-project-id") @@ -1006,9 +1006,9 @@ def test_column_properties_raise_error_for_local_only(self, property_name: str, ("trace_columns", "traces_available_columns_projects_project_id_traces_available_columns_post"), ], ) - @patch("galileo.shared.project_resolver.Projects") - @patch("galileo.log_stream.SplunkAOConfig") - @patch("galileo.log_stream.LogStreams") + @patch("splunk_ao.shared.project_resolver.Projects") + @patch("splunk_ao.log_stream.SplunkAOConfig") + @patch("splunk_ao.log_stream.LogStreams") def test_column_properties_raise_error_on_empty_response( self, mock_logstreams_class: MagicMock, @@ -1030,7 +1030,7 @@ def test_column_properties_raise_error_on_empty_response( mock_config = MagicMock() mock_config_class.get.return_value = mock_config - with patch(f"galileo.log_stream.{api_func_name}") as mock_api_func: + with patch(f"splunk_ao.log_stream.{api_func_name}") as mock_api_func: mock_api_func.sync.return_value = None log_stream = LogStream.get(name="Test Stream", project_id="test-project-id") @@ -1085,7 +1085,7 @@ class TestProjectNotFoundErrorBackwardCompat: ResourceNotFoundError inherits from NotFoundError. """ - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_raises_resource_not_found_error_subclass( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -1101,7 +1101,7 @@ def test_create_raises_resource_not_found_error_subclass( log_stream.create() assert isinstance(exc_info.value, ResourceNotFoundError) - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_create_skips_api_when_no_identifier_anywhere( self, mock_projects_class: MagicMock, reset_configuration: None, monkeypatch: pytest.MonkeyPatch ) -> None: @@ -1128,7 +1128,7 @@ def test_create_skips_api_when_no_identifier_anywhere( log_stream.create() mock_projects_class.assert_not_called() - @patch("galileo.shared.project_resolver.Projects") + @patch("splunk_ao.shared.project_resolver.Projects") def test_resolver_does_not_swallow_unrelated_value_error( self, mock_projects_class: MagicMock, reset_configuration: None ) -> None: diff --git a/tests/test_log_streams_metrics.py b/tests/test_log_streams_metrics.py index edfe259e..77ee6de6 100644 --- a/tests/test_log_streams_metrics.py +++ b/tests/test_log_streams_metrics.py @@ -4,12 +4,12 @@ import pytest -from galileo.log_streams import LogStream, LogStreams, enable_metrics -from galileo.projects import Project from galileo.resources.models import ProjectCreateResponse, ScorerResponse, ScorerTypes from galileo.resources.models.log_stream_response import LogStreamResponse -from galileo.schema.metrics import SplunkAOMetrics, LocalMetricConfig -from galileo.utils.metrics import create_metric_configs +from splunk_ao.log_streams import LogStream, LogStreams, enable_metrics +from splunk_ao.projects import Project +from splunk_ao.schema.metrics import LocalMetricConfig, SplunkAOMetrics +from splunk_ao.utils.metrics import create_metric_configs @pytest.fixture(autouse=True) @@ -78,8 +78,8 @@ def mock_scorers(): class TestLogStreamMetrics: """Test cases for log stream metrics functionality.""" - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_create_metric_configs_with_builtin_metrics( self, mock_scorer_settings_class, mock_scorers_class, mock_scorers ) -> None: @@ -104,8 +104,8 @@ def test_create_metric_configs_with_builtin_metrics( # Verify no local metrics assert len(local_metrics) == 0 - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_create_metric_configs_with_local_metrics(self, mock_scorer_settings, mock_scorers_class) -> None: """Test create_metric_configs with local metric configs.""" @@ -126,8 +126,8 @@ def custom_scorer(trace_or_span) -> float: assert local_metrics[0].name == "custom_metric" assert len(scorers) == 0 - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_create_metric_configs_with_mixed_metrics( self, mock_scorer_settings_class, mock_scorers_class, mock_scorers ) -> None: @@ -155,7 +155,7 @@ def custom_scorer(trace_or_span) -> float: def test_log_stream_enable_metrics_instance_method(self, mock_log_stream) -> None: """Test LogStream instance enable_metrics method.""" - with patch("galileo.log_streams.create_metric_configs") as mock_create_configs: + with patch("splunk_ao.log_streams.create_metric_configs") as mock_create_configs: mock_create_configs.return_value = ([], []) # Test instance method @@ -174,9 +174,9 @@ def test_log_stream_enable_metrics_missing_ids(self) -> None: with pytest.raises(ValueError, match="Log stream must have id and project_id to enable metrics"): log_stream.enable_metrics(["correctness"]) - @patch("galileo.log_streams.Projects") + @patch("splunk_ao.log_streams.Projects") @patch.object(LogStreams, "get") - @patch("galileo.log_streams.create_metric_configs") + @patch("splunk_ao.log_streams.create_metric_configs") def test_logstreams_enable_metrics_with_explicit_params( self, mock_create_configs, mock_get, mock_projects_class, mock_project, mock_log_stream ) -> None: @@ -206,8 +206,8 @@ def test_logstreams_enable_metrics_with_explicit_params( assert local_metrics == [] @patch.object(LogStreams, "get") - @patch("galileo.log_streams.create_metric_configs") - @patch("galileo.projects.Projects.get_with_env_fallbacks") + @patch("splunk_ao.log_streams.create_metric_configs") + @patch("splunk_ao.projects.Projects.get_with_env_fallbacks") def test_logstreams_enable_metrics_gets_project_correctly( self, mock_get_with_env_fallbacks, mock_create_configs, mock_get, mock_log_stream, mock_project ) -> None: @@ -232,9 +232,9 @@ def test_logstreams_enable_metrics_gets_project_correctly( # Verify return value is just local metrics assert local_metrics == [] - @patch("galileo.log_streams.Projects") + @patch("splunk_ao.log_streams.Projects") @patch.object(LogStreams, "get") - @patch("galileo.log_streams.create_metric_configs") + @patch("splunk_ao.log_streams.create_metric_configs") def test_logstreams_enable_metrics_with_env_vars( self, mock_create_configs, mock_get, mock_projects_class, mock_project, mock_log_stream ) -> None: @@ -262,7 +262,7 @@ def test_logstreams_enable_metrics_with_env_vars( # Verify return value is just local metrics assert local_metrics == [] - @patch("galileo.log_streams.Projects") + @patch("splunk_ao.log_streams.Projects") def test_logstreams_enable_metrics_project_not_found(self, mock_projects_class) -> None: """Test LogStreams.enable_metrics raises ValueError when project not found.""" # Setup mock to return None @@ -278,7 +278,7 @@ def test_logstreams_enable_metrics_project_not_found(self, mock_projects_class) assert "Project 'Nonexistent Project' not found" in str(exc_info.value) - @patch("galileo.log_streams.Projects") + @patch("splunk_ao.log_streams.Projects") @patch.object(LogStreams, "get") def test_logstreams_enable_metrics_logstream_not_found(self, mock_get, mock_projects_class, mock_project) -> None: """Test LogStreams.enable_metrics raises ValueError when log stream not found.""" @@ -328,9 +328,9 @@ def test_enable_metrics_convenience_function_env_only(self, mock_enable_metrics) # Verify return value is just local metrics assert local_metrics == [] - @patch("galileo.log_streams.Projects") + @patch("splunk_ao.log_streams.Projects") @patch.object(LogStreams, "get") - @patch("galileo.log_streams.create_metric_configs") + @patch("splunk_ao.log_streams.create_metric_configs") def test_enable_metrics_with_env_vars_integration( self, mock_create_configs, mock_get, mock_projects_class, mock_project, mock_log_stream ) -> None: @@ -361,7 +361,7 @@ def test_enable_metrics_with_env_vars_integration( def test_enable_metrics_missing_env_vars(self) -> None: """Test enable_metrics raises ValueError when environment variables are missing.""" # Don't set any environment variables - with patch("galileo.log_streams.Projects") as mock_projects_class: + with patch("splunk_ao.log_streams.Projects") as mock_projects_class: mock_projects_instance = mock_projects_class.return_value mock_projects_instance.get_with_env_fallbacks.return_value = None @@ -376,8 +376,8 @@ def test_enable_metrics_missing_env_vars(self) -> None: class TestCreateMetricConfigsRouting: """Tests for metric type routing in create_metric_configs.""" - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_uuid_string_routes_through_list_by_ids(self, mock_settings_class, mock_scorers_class) -> None: """UUID strings are routed through list_by_ids, not list_by_labels.""" # Given: a scorer resolved via list_by_ids @@ -402,8 +402,8 @@ def test_uuid_string_routes_through_list_by_ids(self, mock_settings_class, mock_ mock_scorers_class.return_value.list_by_labels.assert_not_called() assert len(scorers) == 1 - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_mixed_uuid_and_label(self, mock_settings_class, mock_scorers_class) -> None: """Mix of UUID + enum routes through both list_by_ids and list_by_labels.""" # Given: scorers resolved via both lookup methods @@ -438,7 +438,7 @@ def test_mixed_uuid_and_label(self, mock_settings_class, mock_scorers_class) -> mock_scorers_class.return_value.list_by_labels.assert_called_once() assert len(scorers) == 2 - @patch("galileo.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.Scorers") def test_unknown_uuid_raises_value_error(self, mock_scorers_class) -> None: """UUID string that doesn't match any scorer raises ValueError.""" # Given: no scorers match the UUID @@ -448,8 +448,8 @@ def test_unknown_uuid_raises_value_error(self, mock_scorers_class) -> None: with pytest.raises(ValueError, match="non-existent"): create_metric_configs("project-123", "run-456", ["00000000-0000-0000-0000-000000000099"]) - @patch("galileo.utils.metrics.Scorers") - @patch("galileo.utils.metrics.ScorerSettings") + @patch("splunk_ao.utils.metrics.Scorers") + @patch("splunk_ao.utils.metrics.ScorerSettings") def test_run_id_none_skips_registration(self, mock_settings_class, mock_scorers_class) -> None: """When run_id is None (trigger=True flow), ScorerSettings.create is not called.""" # Given: scorers resolved via labels diff --git a/tests/test_log_streams_pagination.py b/tests/test_log_streams_pagination.py index 63e6116f..5322fa33 100644 --- a/tests/test_log_streams_pagination.py +++ b/tests/test_log_streams_pagination.py @@ -12,11 +12,11 @@ import pytest -from galileo.log_streams import LogStreams from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.list_log_stream_response import ListLogStreamResponse from galileo.resources.models.log_stream_response import LogStreamResponse from galileo.resources.types import UNSET +from splunk_ao.log_streams import LogStreams def _make_response(*, names: list[str], next_token, paginated: bool) -> ListLogStreamResponse: @@ -40,8 +40,8 @@ def _make_response(*, names: list[str], next_token, paginated: bool) -> ListLogS class TestListAllPagination: """Tests for LogStreams._list_all (internal helper).""" - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_paginates_across_multiple_pages( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -60,8 +60,8 @@ def test_list_all_paginates_across_multiple_pages( # Second call passes the token from the first response assert mock_endpoint.sync.call_args_list[1].kwargs["starting_token"] == 5 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_stops_when_paginated_false(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: a single page with paginated=False page = _make_response(names=["only-stream"], next_token=42, paginated=False) @@ -74,8 +74,8 @@ def test_list_all_stops_when_paginated_false(self, mock_config_class: MagicMock, assert len(all_streams) == 1 assert mock_endpoint.sync.call_count == 1 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_stops_when_next_token_is_unset( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -90,8 +90,8 @@ def test_list_all_stops_when_next_token_is_unset( assert len(all_streams) == 2 assert mock_endpoint.sync.call_count == 1 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_uses_larger_page_size(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: a single page mock_endpoint.sync.return_value = _make_response(names=["a"], next_token=None, paginated=True) @@ -104,8 +104,8 @@ def test_list_all_uses_larger_page_size(self, mock_config_class: MagicMock, mock assert kwargs["limit"] == LogStreams._LIST_ALL_PAGE_SIZE assert kwargs["limit"] == 500 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_raises_on_http_validation_error( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -117,8 +117,8 @@ def test_list_all_raises_on_http_validation_error( with pytest.raises(ValueError, match="Failed to list log streams"): LogStreams()._list_all(project_id="proj-1") - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_raises_on_none_response(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: the endpoint returns None (unexpected protocol error) mock_endpoint.sync.return_value = None @@ -127,8 +127,8 @@ def test_list_all_raises_on_none_response(self, mock_config_class: MagicMock, mo with pytest.raises(ValueError, match="Unexpected empty response"): LogStreams()._list_all(project_id="proj-1") - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_breaks_on_non_advancing_token( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -143,8 +143,8 @@ def test_list_all_breaks_on_non_advancing_token( assert len(all_streams) == 1 assert mock_endpoint.sync.call_count == 1 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_all_breaks_on_repeated_seen_token( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -167,8 +167,8 @@ def test_list_all_breaks_on_repeated_seen_token( class TestGetByNamePaginates: """Tests for LogStreams.get(name=...) finding matches across pages.""" - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_get_by_name_finds_match_on_second_page( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -185,8 +185,8 @@ def test_get_by_name_finds_match_on_second_page( assert result.name == "target-stream" assert mock_endpoint.sync.call_count == 2 - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_get_by_name_returns_none_when_missing( self, mock_config_class: MagicMock, mock_endpoint: MagicMock ) -> None: @@ -204,8 +204,8 @@ def test_get_by_name_returns_none_when_missing( class TestListForwardsStartingToken: """Tests that LogStreams.list forwards starting_token to the paginated endpoint.""" - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_forwards_starting_token(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: a single page response mock_endpoint.sync.return_value = _make_response(names=["s1"], next_token=None, paginated=True) @@ -219,8 +219,8 @@ def test_list_forwards_starting_token(self, mock_config_class: MagicMock, mock_e assert kwargs["limit"] == 50 assert kwargs["project_id"] == "proj-1" - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_default_starting_token_is_zero(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: a single page response mock_endpoint.sync.return_value = _make_response(names=[], next_token=None, paginated=True) @@ -251,8 +251,8 @@ def test_list_raises_when_neither_project_id_nor_name_provided(self) -> None: class TestListPropagatesErrors: """Tests that LogStreams.list raises instead of silently returning [] on server errors.""" - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_raises_on_http_validation_error(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: the endpoint returns an HTTPValidationError (e.g. bad starting_token type) mock_endpoint.sync.return_value = HTTPValidationError() @@ -261,8 +261,8 @@ def test_list_raises_on_http_validation_error(self, mock_config_class: MagicMock with pytest.raises(ValueError, match="Failed to list log streams"): LogStreams().list(project_id="proj-1") - @patch("galileo.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") - @patch("galileo.log_streams.SplunkAOConfig") + @patch("splunk_ao.log_streams.list_log_streams_paginated_projects_project_id_log_streams_paginated_get") + @patch("splunk_ao.log_streams.SplunkAOConfig") def test_list_raises_on_none_response(self, mock_config_class: MagicMock, mock_endpoint: MagicMock) -> None: # Given: the endpoint returns None (unexpected protocol error) mock_endpoint.sync.return_value = None diff --git a/tests/test_logger_batch.py b/tests/test_logger_batch.py index 6574f727..82d413a2 100644 --- a/tests/test_logger_batch.py +++ b/tests/test_logger_batch.py @@ -8,12 +8,6 @@ import pytest -from galileo.logger import SplunkAOLogger -from galileo.schema.content_blocks import DataContentBlock, TextContentBlock -from galileo.schema.logged import LoggedTrace, LoggedWorkflowSpan -from galileo.schema.message import LoggedMessage -from galileo.schema.metrics import LocalMetricConfig -from galileo.schema.trace import TracesIngestRequest from galileo_core.schemas.logging.agent import AgentType from galileo_core.schemas.logging.llm import Message, MessageRole from galileo_core.schemas.logging.span import ( @@ -32,6 +26,12 @@ from galileo_core.schemas.protect.response import Response, TraceMetadata from galileo_core.schemas.shared.document import Document from galileo_core.schemas.shared.multimodal import ContentModality +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.schema.content_blocks import DataContentBlock, TextContentBlock +from splunk_ao.schema.logged import LoggedTrace, LoggedWorkflowSpan +from splunk_ao.schema.message import LoggedMessage +from splunk_ao.schema.metrics import LocalMetricConfig +from splunk_ao.schema.trace import TracesIngestRequest from tests.testutils.setup import ( setup_mock_experiments_client, setup_mock_logstreams_client, @@ -54,7 +54,7 @@ def test_galileo_logger_exceptions() -> None: assert str(exc_info.value) == "ingestion_hook can only be used in batch mode" -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.Traces") def test_disable_galileo_logger(mock_traces_client: Mock, monkeypatch, caplog, enable_galileo_logging) -> None: monkeypatch.setenv("SPLUNK_AO_LOGGING_DISABLED", "true") @@ -83,9 +83,9 @@ def test_disable_galileo_logger(mock_traces_client: Mock, monkeypatch, caplog, e mock_traces_client.ingest_traces.assert_not_called() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_single_span_trace_to_galileo( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -130,9 +130,9 @@ def test_single_span_trace_to_galileo( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_all_span_types_with_redacted_fields( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -314,9 +314,9 @@ def test_all_span_types_with_redacted_fields( assert logger._parent_stack == deque() -@patch("galileo.experiments.Experiments") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.experiments.Experiments") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_single_span_trace_to_galileo_experiment_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_experiments_client: Mock ) -> None: @@ -349,9 +349,9 @@ def test_single_span_trace_to_galileo_experiment_id( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_nested_span_trace_to_galileo( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -400,9 +400,9 @@ def test_nested_span_trace_to_galileo( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_agent_span(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -430,9 +430,9 @@ def test_add_agent_span(mock_traces_client: Mock, mock_projects_client: Mock, mo assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_protect_tool_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -513,9 +513,9 @@ def test_add_protect_tool_span( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_multi_span_trace_to_galileo( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -581,9 +581,9 @@ def test_multi_span_trace_to_galileo( @pytest.mark.asyncio -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_single_span_trace_to_galileo_with_async( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -638,9 +638,9 @@ def local_scorer(step: Trace | Span) -> int: assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_str_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -664,9 +664,9 @@ def test_retriever_span_str_output( assert payload.traces[0].spans[0].output == [Document(content="response", metadata=None)] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_list_str_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -693,9 +693,9 @@ def test_retriever_span_list_str_output( ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_dict_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -728,9 +728,9 @@ def test_retriever_span_dict_output( assert payload.traces[0].spans[1].output == [Document(content="response2", metadata={"key": "value"})] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_list_dict_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -775,9 +775,9 @@ def test_retriever_span_list_dict_output( ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_document_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -805,9 +805,9 @@ def test_retriever_span_document_output( assert payload.traces[0].spans[0].output == [Document(content="response", metadata={"key": "value"})] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_list_document_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -838,9 +838,9 @@ def test_retriever_span_list_document_output( ] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_retriever_span_none_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -862,9 +862,9 @@ def test_retriever_span_none_output( assert payload.traces[0].spans[0].output == [Document(content="", metadata={})] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_all_spans(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -901,9 +901,9 @@ def test_conclude_all_spans(mock_traces_client: Mock, mock_projects_client: Mock assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_with_conclude_all_spans( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -948,9 +948,9 @@ def test_flush_with_conclude_all_spans( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_workflow_keeps_message_trace_gets_string( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -982,9 +982,9 @@ def test_flush_workflow_keeps_message_trace_gets_string( assert workflow_span.output.role == MessageRole.assistant -@patch("galileo.logger.logger.Projects.get") -@patch("galileo.projects.create_project_projects_post") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.Projects.get") +@patch("splunk_ao.projects.create_project_projects_post") +@patch("splunk_ao.logger.logger.Traces") def test_galileo_logger_failed_creating_project( mock_traces_client: Mock, galileo_resources_api_projects: Mock, mock_projects_get: Mock ) -> None: @@ -1331,9 +1331,9 @@ def test_get_last_output_llm_message_raw() -> None: assert output.role == MessageRole.assistant -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_create(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -1353,9 +1353,9 @@ def test_session_create(mock_traces_client: Mock, mock_projects_client: Mock, mo assert logger.session_id == session_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_create_with_metadata( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1379,9 +1379,9 @@ def test_session_create_with_metadata( assert logger.session_id == session_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_create_empty_values( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1401,9 +1401,9 @@ def test_session_create_empty_values( assert logger.session_id == session_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_clear(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -1421,9 +1421,9 @@ def test_session_clear(mock_traces_client: Mock, mock_projects_client: Mock, moc assert logger.session_id is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_session_id_on_flush( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1447,9 +1447,9 @@ def test_session_id_on_flush( assert str(payload.session_id) == session_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9c" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_set_session_id(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -1473,9 +1473,9 @@ def test_set_session_id(mock_traces_client: Mock, mock_projects_client: Mock, mo assert payload.session_id == UUID(session_id) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_start_session_with_external_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1545,9 +1545,9 @@ def test_start_session_with_external_id( assert payload.session_id == session_id -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_with_project_id_and_log_stream_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1566,9 +1566,9 @@ def test_logger_init_with_project_id_and_log_stream_id( assert logger.log_stream_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9b" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_with_project_id_and_log_stream_name( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1585,9 +1585,9 @@ def test_logger_init_with_project_id_and_log_stream_name( assert logger.log_stream_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9b" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_with_project_name_and_log_stream_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1604,9 +1604,9 @@ def test_logger_init_with_project_name_and_log_stream_id( assert logger.log_stream_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9b" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_with_project_name_and_experiment_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1624,9 +1624,9 @@ def test_logger_init_with_project_name_and_experiment_id( assert logger.experiment_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9b" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_logger_init_with_project_id_and_experiment_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1646,9 +1646,9 @@ def test_logger_init_with_project_id_and_experiment_id( assert logger.experiment_id == "6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9b" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_ingestion_hook_sync( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1671,9 +1671,9 @@ def test_ingestion_hook_sync( @pytest.mark.asyncio -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_ingestion_hook_async( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1696,9 +1696,9 @@ async def test_ingestion_hook_async( @pytest.mark.asyncio -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_ingest_traces_methods( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1717,9 +1717,9 @@ async def test_ingest_traces_methods( assert mock_traces_client_instance.ingest_traces.call_count == 2 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_ingestion_hook_with_real_redaction( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1763,9 +1763,9 @@ def redact_and_forward(ingest_request: TracesIngestRequest): assert payload.traces[0].input == "This is a [REDACTED]" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_single_llm_span_trace_ingestion( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1812,9 +1812,9 @@ def test_add_single_llm_span_trace_ingestion( assert logger._parent_stack == deque() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_with_unconcluded_trace_redaction( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1889,9 +1889,9 @@ def test_get_last_output_with_redacted_output() -> None: ), ], ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_start_trace_auto_conversion( mock_traces_client: Mock, mock_projects_client: Mock, @@ -1920,9 +1920,9 @@ def test_start_trace_auto_conversion( assert getattr(payload_trace, attr) == expected_value, f"payload.{attr} mismatch" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_multimodal_input_not_stringified_at_trace_level( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1983,9 +1983,9 @@ def test_multimodal_input_not_stringified_at_trace_level( ), ], ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_start_trace_valid_input_types( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, valid_input: object ) -> None: @@ -2145,9 +2145,9 @@ class TestMultipleLoggerInstanceIsolation: on one logger do not affect another logger's state or trace hierarchy. """ - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def test_loggers_have_isolated_state( self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2201,9 +2201,9 @@ def test_loggers_have_isolated_state( assert isinstance(workflow_a, WorkflowSpan) and len(workflow_a.spans) == 1 assert workflow_a.spans[0].name == "llm_a" - @patch("galileo.logger.logger.LogStreams") - @patch("galileo.logger.logger.Projects") - @patch("galileo.logger.logger.Traces") + @patch("splunk_ao.logger.logger.LogStreams") + @patch("splunk_ao.logger.logger.Projects") + @patch("splunk_ao.logger.logger.Traces") def test_reset_only_affects_own_logger( self, mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2299,7 +2299,7 @@ def record_agent_control_auto_enable(_logger): # When: creating an ingestion-hook logger with ( - patch("galileo.logger.logger.atexit.register", side_effect=record_atexit_register), + patch("splunk_ao.logger.logger.atexit.register", side_effect=record_atexit_register), patch.object( SplunkAOLogger, "_auto_enable_agent_control_if_available", @@ -2314,9 +2314,9 @@ def record_agent_control_auto_enable(_logger): assert calls == [("atexit", "terminate"), ("agent_control", None)] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_standard_init_registers_atexit_before_agent_control_auto_enable( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2334,7 +2334,7 @@ def record_agent_control_auto_enable(_logger): # When: creating the logger with ( - patch("galileo.logger.logger.atexit.register", side_effect=record_atexit_register), + patch("splunk_ao.logger.logger.atexit.register", side_effect=record_atexit_register), patch.object( SplunkAOLogger, "_auto_enable_agent_control_if_available", @@ -2349,9 +2349,9 @@ def record_agent_control_auto_enable(_logger): assert calls == [("atexit", "terminate"), ("agent_control", None)] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_flush_does_not_propagate_exceptions( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2378,9 +2378,9 @@ def test_flush_does_not_propagate_exceptions( assert result is None or result == [] -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_terminate_does_not_propagate_exceptions( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2409,9 +2409,9 @@ def test_terminate_does_not_propagate_exceptions( pytest.fail(f"terminate() should not propagate exceptions, but raised: {e}") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_ingest_traces_lazy_creates_client_for_ingestion_hook( mock_traces_cls: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2450,9 +2450,9 @@ def capture_hook(ingest_request: TracesIngestRequest) -> None: mock_traces_instance.ingest_traces.assert_called_once_with(captured_payload) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_ingest_traces_reuses_existing_client( mock_traces_cls: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: diff --git a/tests/test_logger_distributed.py b/tests/test_logger_distributed.py index 8429fb69..7af8963d 100644 --- a/tests/test_logger_distributed.py +++ b/tests/test_logger_distributed.py @@ -8,14 +8,14 @@ import pytest -from galileo.logger import SplunkAOLogger -from galileo.logger.logger import SplunkAOLoggerException -from galileo.schema.trace import SpansIngestRequest, SpanUpdateRequest, TracesIngestRequest, TraceUpdateRequest from galileo_core.schemas.logging.llm import Message from galileo_core.schemas.protect.execution_status import ExecutionStatus from galileo_core.schemas.protect.payload import Payload from galileo_core.schemas.protect.response import Response, TraceMetadata from galileo_core.schemas.shared.document import Document +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.logger.logger import SplunkAOLoggerException +from splunk_ao.schema.trace import SpansIngestRequest, SpanUpdateRequest, TracesIngestRequest, TraceUpdateRequest from tests.testutils.setup import ( setup_mock_logstreams_client, setup_mock_projects_client, @@ -32,7 +32,7 @@ def test_galileo_logger_exceptions() -> None: assert str(exc_info.value) == "User cannot specify both a log stream and an experiment." -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.Traces") def test_disable_galileo_logger(mock_traces_client: Mock, monkeypatch, caplog) -> None: monkeypatch.setenv("SPLUNK_AO_LOGGING_DISABLED", "true") @@ -64,9 +64,9 @@ def test_disable_galileo_logger(mock_traces_client: Mock, monkeypatch, caplog) - mock_traces_client.update_span.assert_not_called() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_start_trace(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -97,10 +97,10 @@ def test_start_trace(mock_traces_client: Mock, mock_projects_client: Mock, mock_ assert request.traces[0].metrics.duration_ns == 1_000_000 -@patch("galileo.logger.logger.IngestTraces") -@patch("galileo.logger.logger.Traces") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") +@patch("splunk_ao.logger.logger.IngestTraces") +@patch("splunk_ao.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") def test_distributed_logger_uses_ingest_client_when_ingest_service_is_available( mock_projects_client: Mock, mock_logstreams_client: Mock, mock_traces_client: Mock, mock_ingest_traces_client: Mock ) -> None: @@ -118,9 +118,9 @@ def test_distributed_logger_uses_ingest_client_when_ingest_service_is_available( mock_traces_client.assert_not_called() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_nested_distributed_spans_submit_independently( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -145,9 +145,9 @@ def test_nested_distributed_spans_submit_independently( assert span_tasks[1].request.parent_id == workflow.id -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_llm_span(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -212,9 +212,9 @@ def test_add_llm_span(mock_traces_client: Mock, mock_projects_client: Mock, mock assert request.spans[0].step_number == 1 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_protect_tool_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -317,9 +317,9 @@ def test_add_protect_tool_span( assert protect_span.user_metadata == metadata -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace(mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock) -> None: mock_traces_client_instance = setup_mock_traces_client(mock_traces_client) setup_mock_projects_client(mock_projects_client) @@ -371,9 +371,9 @@ def test_conclude_trace(mock_traces_client: Mock, mock_projects_client: Mock, mo assert request.duration_ns == 1_000_000 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_with_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -458,9 +458,9 @@ def test_conclude_trace_with_span( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_and_start_new_trace( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -577,9 +577,9 @@ def test_conclude_trace_and_start_new_trace( assert request.traces[0].metrics.duration_ns is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_with_nested_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -710,9 +710,9 @@ def test_conclude_trace_with_nested_span( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_all_with_nested_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -833,9 +833,9 @@ def test_conclude_all_with_nested_span( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_with_agent_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -969,9 +969,9 @@ def test_conclude_trace_with_agent_span( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_trace_with_multiple_nested_spans( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1238,9 +1238,9 @@ def test_trace_with_multiple_nested_spans( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_trace_with_nested_span_and_sibling( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1392,9 +1392,9 @@ def test_trace_with_nested_span_and_sibling( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_llm_span_and_conclude_existing_trace( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1470,9 +1470,9 @@ def test_add_llm_span_and_conclude_existing_trace( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_nested_span_and_conclude_existing_trace( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1594,9 +1594,9 @@ def test_add_nested_span_and_conclude_existing_trace( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_llm_span_and_conclude_existing_workflow_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1675,9 +1675,9 @@ def test_add_llm_span_and_conclude_existing_workflow_span( assert request.status_code == 200 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_add_nested_span_and_conclude_existing_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1802,9 +1802,9 @@ def test_add_nested_span_and_conclude_existing_span( assert request.status_code == 200 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_catch_error_trace_span_ids_in_batch_mode( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, caplog ) -> None: @@ -1813,15 +1813,17 @@ def test_catch_error_trace_span_ids_in_batch_mode( setup_mock_logstreams_client(mock_logstreams_client) with pytest.raises(SplunkAOLoggerException): - SplunkAOLogger(project="my_project", log_stream="my_log_stream", trace_id="6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9d") + SplunkAOLogger( + project="my_project", log_stream="my_log_stream", trace_id="6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9d" + ) with pytest.raises(SplunkAOLoggerException): SplunkAOLogger(project="my_project", log_stream="my_log_stream", span_id="6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9e") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_catch_error_mismatched_trace_span_ids( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, caplog, enable_galileo_logging ) -> None: @@ -1854,9 +1856,9 @@ def test_catch_error_mismatched_trace_span_ids( assert logger._parent_stack[1].id == UUID("6c4e3f7e-4a9a-4e7e-8c1f-3a9a3a9a3a9e") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_tracing_headers_with_workflow_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1879,9 +1881,9 @@ def test_get_tracing_headers_with_workflow_span( assert headers["X-Galileo-Parent-ID"] == str(workflow_span.id) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_tracing_headers_with_agent_span( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1904,9 +1906,9 @@ def test_get_tracing_headers_with_agent_span( assert headers["X-Galileo-Parent-ID"] == str(agent_span.id) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_tracing_headers_batch_mode_error( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1924,9 +1926,9 @@ def test_get_tracing_headers_batch_mode_error( assert "only supported in distributed mode" in str(exc_info.value) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_tracing_headers_no_trace_error( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1943,9 +1945,9 @@ def test_get_tracing_headers_no_trace_error( assert "Start trace before getting tracing headers" in str(exc_info.value) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_update_trace_output_and_duration_streaming( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -1992,9 +1994,9 @@ def test_update_trace_output_and_duration_streaming( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_update_span_output_and_duration_streaming( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2043,9 +2045,9 @@ def test_update_span_output_and_duration_streaming( assert request.status_code == 200 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_update_trace_with_none_duration( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2082,9 +2084,9 @@ def test_update_trace_with_none_duration( assert request.duration_ns is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_update_span_with_none_duration( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2123,9 +2125,9 @@ def test_update_span_with_none_duration( assert request.duration_ns is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_update_trace_and_span_with_duration_in_nested_structure( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2176,9 +2178,9 @@ def test_update_trace_and_span_with_duration_in_nested_structure( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_inherits_last_llm_child_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2227,9 +2229,9 @@ def test_conclude_trace_inherits_last_llm_child_output( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_with_multiple_llm_children_inherits_last( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2280,9 +2282,9 @@ def test_conclude_trace_with_multiple_llm_children_inherits_last( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_inherits_last_workflow_span_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2337,9 +2339,9 @@ def test_conclude_trace_inherits_last_workflow_span_output( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_trace_explicit_output_overrides_child( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2381,9 +2383,9 @@ def test_conclude_trace_explicit_output_overrides_child( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_conclude_workflow_span_inherits_last_child_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2435,9 +2437,9 @@ def test_conclude_workflow_span_inherits_last_child_output( assert request.duration_ns == 3_000_000 -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_distributed_flush_concludes_unconcluded_trace( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2494,9 +2496,9 @@ def test_distributed_flush_concludes_unconcluded_trace( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_distributed_flush_no_op_if_already_concluded( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2550,9 +2552,9 @@ def test_distributed_flush_no_op_if_already_concluded( assert request.is_complete -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_distributed_flush_waits_for_tasks( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: @@ -2584,9 +2586,9 @@ def test_distributed_flush_waits_for_tasks( assert logger._task_handler.all_tasks_completed() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_terminate_stops_task_handler_when_agent_control_unregister_fails( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock ) -> None: @@ -2613,9 +2615,9 @@ def test_terminate_stops_task_handler_when_agent_control_unregister_fails( task_handler.terminate.assert_called_once() -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_batch_mode_flush_still_uses_get_last_output( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, enable_galileo_logging ) -> None: diff --git a/tests/test_logger_timestamps.py b/tests/test_logger_timestamps.py index 665bbca8..56bae4a1 100644 --- a/tests/test_logger_timestamps.py +++ b/tests/test_logger_timestamps.py @@ -1,12 +1,12 @@ from datetime import datetime, timedelta, timezone from unittest.mock import Mock, patch -from galileo.logger import SplunkAOLogger +from splunk_ao.logger import SplunkAOLogger from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") def test_rapid_span_creation_ensures_uniqueness(mock_projects_client: Mock, mock_logstreams_client: Mock): """Tests that creating spans in a tight loop results in unique, monotonically increasing timestamps.""" setup_mock_projects_client(mock_projects_client) @@ -23,8 +23,8 @@ def test_rapid_span_creation_ensures_uniqueness(mock_projects_client: Mock, mock assert timestamps == sorted(timestamps), "Timestamps should be monotonically increasing" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") def test_user_provided_timestamps_are_respected(mock_projects_client: Mock, mock_logstreams_client: Mock): """Tests that timestamps provided by the user are not modified.""" setup_mock_projects_client(mock_projects_client) @@ -46,8 +46,8 @@ def test_user_provided_timestamps_are_respected(mock_projects_client: Mock, mock assert span_timestamps == timestamps, "User-provided timestamps should be respected" -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") def test_mixed_default_and_user_timestamps(mock_projects_client: Mock, mock_logstreams_client: Mock): """Tests that the internal state for default timestamp generation is not affected by user-provided timestamps.""" setup_mock_projects_client(mock_projects_client) diff --git a/tests/test_metric.py b/tests/test_metric.py index 30df958e..105c646b 100644 --- a/tests/test_metric.py +++ b/tests/test_metric.py @@ -5,13 +5,13 @@ import pytest -from galileo.metric import CodeMetric, LlmMetric, LocalMetric, Metric from galileo.resources.models import HTTPValidationError, OutputTypeEnum, ScorerTypes from galileo.resources.models.invalid_result import InvalidResult from galileo.resources.models.task_result_status import TaskResultStatus -from galileo.shared.base import SyncState -from galileo.shared.exceptions import APIError, ValidationError from galileo_core.schemas.logging.step import StepType +from splunk_ao.metric import CodeMetric, LlmMetric, LocalMetric, Metric +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.exceptions import APIError, ValidationError # Test fixtures and helper functions @@ -208,8 +208,8 @@ def test_init_llm_scorer_without_user_prompt_raises_error(self, reset_configurat class TestMetricCreate: """Test suite for Metric.create() method.""" - @patch("galileo.metric.Metrics") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Metrics") + @patch("splunk_ao.metric.Scorers") def test_create_persists_metric_to_api( self, mock_scorers_class: MagicMock, mock_metrics_class: MagicMock, reset_configuration: None ) -> None: @@ -253,8 +253,8 @@ def test_create_persists_metric_to_api( assert metric.id == scorer_id assert metric.is_synced() - @patch("galileo.metric.Metrics") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Metrics") + @patch("splunk_ao.metric.Scorers") def test_create_forwards_ground_truth( self, mock_scorers_class: MagicMock, mock_metrics_class: MagicMock, reset_configuration: None ) -> None: @@ -299,7 +299,7 @@ def test_create_forwards_ground_truth( assert kwargs["ground_truth"] is True assert metric.ground_truth is True - @patch("galileo.metric.Metrics") + @patch("splunk_ao.metric.Metrics") def test_create_handles_api_failure(self, mock_metrics_class: MagicMock, reset_configuration: None) -> None: """Test create() handles API failures and sets state correctly.""" mock_service = MagicMock() @@ -317,7 +317,7 @@ def test_create_handles_api_failure(self, mock_metrics_class: MagicMock, reset_c class TestMetricGet: """Test suite for Metric.get() class method.""" - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_get_by_name_returns_metric(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test get() with name returns a synced metric instance.""" mock_service = MagicMock() @@ -347,7 +347,7 @@ def test_get_by_name_returns_metric(self, mock_scorers_class: MagicMock, reset_c assert metric.name == "Test Metric" assert metric.is_synced() - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_get_by_id_returns_metric(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test get() with id returns a synced metric instance.""" mock_service = MagicMock() @@ -375,7 +375,7 @@ def test_get_by_id_returns_metric(self, mock_scorers_class: MagicMock, reset_con assert metric.id == metric_id assert metric.is_synced() - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_get_returns_none_when_not_found(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test get() returns None when metric is not found.""" mock_service = MagicMock() @@ -402,7 +402,7 @@ def test_get_validates_parameters(self, kwargs: dict, expected_error: str, reset class TestMetricList: """Test suite for Metric.list() class method.""" - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_list_returns_all_metrics(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test list() returns a list of synced metric instances.""" mock_service = MagicMock() @@ -433,7 +433,7 @@ def test_list_returns_all_metrics(self, mock_scorers_class: MagicMock, reset_con assert all(isinstance(m, Metric) for m in metrics) assert all(m.is_synced() for m in metrics) - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_list_with_name_filter(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test list() with name filter.""" mock_service = MagicMock() @@ -460,7 +460,7 @@ def test_list_with_name_filter(self, mock_scorers_class: MagicMock, reset_config assert len(metrics) == 1 assert metrics[0].name == "Factuality Metric" - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_list_with_scorer_types_filter(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test list() with scorer types filter.""" mock_service = MagicMock() @@ -475,8 +475,8 @@ def test_list_with_scorer_types_filter(self, mock_scorers_class: MagicMock, rese class TestMetricDelete: """Test suite for Metric.delete() method.""" - @patch("galileo.metric.Metrics") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Metrics") + @patch("splunk_ao.metric.Scorers") def test_delete_removes_metric( self, mock_scorers_class: MagicMock, mock_metrics_class: MagicMock, reset_configuration: None ) -> None: @@ -520,7 +520,7 @@ def test_delete_raises_error_for_local_only(self, reset_configuration: None) -> class TestMetricRefresh: """Test suite for Metric.refresh() method.""" - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_refresh_updates_attributes(self, mock_scorers_class: MagicMock, reset_configuration: None) -> None: """Test refresh() updates all attributes from the API.""" mock_service = MagicMock() @@ -581,7 +581,7 @@ def test_refresh_raises_error_for_local_only(self, reset_configuration: None) -> with pytest.raises(ValueError, match="Metric ID is not set"): metric.refresh() - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_refresh_raises_error_when_metric_no_longer_exists( self, mock_scorers_class: MagicMock, reset_configuration: None ) -> None: @@ -664,8 +664,8 @@ def test_update_with_invalid_fields_raises_value_error(self, reset_configuration with pytest.raises(ValueError, match="Invalid update fields"): metric.update(prompt="new prompt", model="gpt-4o") - @patch("galileo.metric.update_scorers_scorer_id_patch") - @patch("galileo.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.update_scorers_scorer_id_patch") + @patch("splunk_ao.metric.SplunkAOConfig.get") def test_update_calls_api_and_syncs_attributes( self, mock_config_get: MagicMock, mock_update_patch: MagicMock, reset_configuration: None ) -> None: @@ -705,8 +705,8 @@ def test_update_calls_api_and_syncs_attributes( assert metric.tags == ["new-tag"] assert metric.sync_state == SyncState.SYNCED - @patch("galileo.metric.update_scorers_scorer_id_patch") - @patch("galileo.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.update_scorers_scorer_id_patch") + @patch("splunk_ao.metric.SplunkAOConfig.get") def test_update_handles_api_failure( self, mock_config_get: MagicMock, mock_update_patch: MagicMock, reset_configuration: None ) -> None: @@ -724,8 +724,8 @@ def test_update_handles_api_failure( assert metric.sync_state == SyncState.FAILED_SYNC - @patch("galileo.metric.update_scorers_scorer_id_patch") - @patch("galileo.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.update_scorers_scorer_id_patch") + @patch("splunk_ao.metric.SplunkAOConfig.get") def test_update_raises_api_error_for_validation_error_response( self, mock_config_get: MagicMock, mock_update_patch: MagicMock, reset_configuration: None ) -> None: @@ -743,8 +743,8 @@ def test_update_raises_api_error_for_validation_error_response( with pytest.raises(APIError, match="Metric update validation error"): metric.update(name="New Name") - @patch("galileo.metric.update_scorers_scorer_id_patch") - @patch("galileo.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.update_scorers_scorer_id_patch") + @patch("splunk_ao.metric.SplunkAOConfig.get") def test_update_raises_api_error_for_none_response( self, mock_config_get: MagicMock, mock_update_patch: MagicMock, reset_configuration: None ) -> None: @@ -772,7 +772,7 @@ def test_str_and_repr(self, reset_configuration: None) -> None: assert str(metric) == "LlmMetric(name='Test Metric', id='test-id-123', scorer_type='llm')" assert "model=" in repr(metric) and "judges=" in repr(metric) - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.Scorers") def test_populate_from_scorer_response_handles_unset_values( self, mock_scorers_class: MagicMock, reset_configuration: None ) -> None: @@ -870,12 +870,12 @@ def test_init_without_output_type_defaults_to_none(self, reset_configuration: No class TestCodeMetricCreate: """Test suite for CodeMetric.create() method.""" - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.Scorers") def test_create_persists_code_metric_to_api( self, mock_scorers_class: MagicMock, @@ -954,12 +954,12 @@ def test_create_persists_code_metric_to_api( assert metric.id == scorer_id assert metric.is_synced() - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.Scorers") def test_create_forwards_output_type_to_scorer_request( self, mock_scorers_class: MagicMock, @@ -998,10 +998,10 @@ def test_create_forwards_output_type_to_scorer_request( create_scorer_call = mock_create_scorers.sync.call_args assert create_scorer_call.kwargs["body"].output_type == OutputTypeEnum.PERCENTAGE - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_handles_scorer_creation_failure( self, mock_create_scorers: MagicMock, @@ -1035,11 +1035,11 @@ def test_create_handles_scorer_creation_failure( assert metric.sync_state == SyncState.FAILED_SYNC - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_handles_version_creation_failure( self, mock_create_scorers: MagicMock, @@ -1079,12 +1079,12 @@ def test_create_handles_version_creation_failure( assert metric.sync_state == SyncState.FAILED_SYNC - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.Scorers") def test_create_with_different_node_levels( self, mock_scorers_class: MagicMock, @@ -1140,12 +1140,12 @@ def test_create_with_different_node_levels( # Verify the node_level is set on the metric itself assert metric.node_level == node_level - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.Scorers") def test_create_with_required_metrics( self, mock_scorers_class: MagicMock, @@ -1207,7 +1207,7 @@ def test_create_with_required_metrics( create_scorer_call = mock_create_scorers.sync.call_args assert create_scorer_call.kwargs["body"].required_scorers == required_metrics - @patch("galileo.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.SplunkAOConfig.get") def test_create_reads_code_file_correctly( self, mock_config: MagicMock, @@ -1234,15 +1234,15 @@ def score(trace): code_file = create_temp_code_file(filename="complex_scorer.py", content=expected_content) with ( - patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") as mock_validate_post, + patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") as mock_validate_post, patch( - "galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get" + "splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get" ) as mock_validate_get, - patch("galileo.metric.create_scorers_post") as mock_create_scorers, + patch("splunk_ao.metric.create_scorers_post") as mock_create_scorers, patch( - "galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post" + "splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post" ) as mock_create_version, - patch("galileo.metric.Scorers") as mock_scorers_class, + patch("splunk_ao.metric.Scorers") as mock_scorers_class, ): # Mock validation flow mock_validate_post.sync.return_value = mock_validation_response() @@ -1267,8 +1267,8 @@ def score(trace): assert hasattr(body, "file") assert hasattr(body.file, "payload") - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.create_scorers_post") def test_load_code_with_nonexistent_file_raises_validation_error( self, mock_create_scorers: MagicMock, @@ -1287,10 +1287,10 @@ def test_load_code_with_nonexistent_file_raises_validation_error( with pytest.raises(ValidationError, match="Code file not found"): metric.load_code("/nonexistent/file.py").create() - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_handles_none_scorer_response( self, mock_create_scorers: MagicMock, @@ -1324,11 +1324,11 @@ def test_create_handles_none_scorer_response( assert metric.sync_state == SyncState.FAILED_SYNC - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_handles_none_version_response( self, mock_create_scorers: MagicMock, @@ -1368,10 +1368,10 @@ def test_create_handles_none_version_response( assert metric.sync_state == SyncState.FAILED_SYNC - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_propagates_validation_error( self, mock_create_scorers: MagicMock, @@ -1405,10 +1405,10 @@ def test_create_propagates_validation_error( with pytest.raises(ValidationError, match="Invalid configuration"): metric.load_code(str(code_file)).create() - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_scorers_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_scorers_post") def test_create_sets_failed_sync_state_on_general_exception( self, mock_create_scorers: MagicMock, @@ -1445,9 +1445,9 @@ def test_create_sets_failed_sync_state_on_general_exception( assert metric.sync_state == SyncState.FAILED_SYNC assert metric._last_error == runtime_error - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") def test_create_handles_validation_failure( self, mock_validate_post: MagicMock, @@ -1475,13 +1475,13 @@ def test_create_handles_validation_failure( with pytest.raises(ValidationError, match="Code validation failed"): metric.load_code(str(code_file)).create() - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.SplunkAOConfig.get") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.Scorers") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.SplunkAOConfig.get") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.Scorers") def test_create_polls_until_validation_complete( self, mock_scorers_class: MagicMock, @@ -1534,11 +1534,11 @@ def test_create_polls_until_validation_complete( assert mock_sleep.call_count == 2 assert metric.is_synced() - @patch("galileo.metric.time.time") - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.time.time") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_timeout( self, mock_config, @@ -1568,9 +1568,9 @@ def test_create_validation_timeout( with pytest.raises(ValidationError, match="Code validation timed out"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_post_returns_none( self, mock_config, mock_validate_post, mock_validate_get, create_temp_code_file, mock_api_client ) -> None: @@ -1586,9 +1586,9 @@ def test_create_validation_post_returns_none( with pytest.raises(ValueError, match="Failed to validate code: No response from API"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_get_returns_none( self, mock_config, @@ -1611,9 +1611,9 @@ def test_create_validation_get_returns_none( with pytest.raises(ValueError, match="Failed to get validation result: No response from API"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_unknown_status( self, mock_config, @@ -1639,9 +1639,9 @@ def test_create_validation_unknown_status( with pytest.raises(ValueError, match="Unknown task status"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_failed_status( self, mock_config, @@ -1667,9 +1667,9 @@ def test_create_validation_failed_status( with pytest.raises(ValidationError, match="Code validation failed: Syntax error in code"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_failed_status_no_message( self, mock_config, @@ -1695,9 +1695,9 @@ def test_create_validation_failed_status_no_message( with pytest.raises(ValidationError, match="Code validation failed"): metric.create() - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_invalid_result( self, mock_config, @@ -1739,12 +1739,12 @@ def test_create_validation_invalid_result( with pytest.raises(ValidationError, match="Code validation failed: Missing required function: evaluate"): metric.create() - @patch("galileo.metric.Scorers") - @patch("galileo.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") - @patch("galileo.metric.create_scorers_post") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.Scorers") + @patch("splunk_ao.metric.create_code_scorer_version_scorers_scorer_id_version_code_post") + @patch("splunk_ao.metric.create_scorers_post") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_create_validation_result_as_string( self, mock_config, @@ -1792,11 +1792,11 @@ def test_create_validation_result_as_string( class TestCodeMetricValidationConfiguration: """Test suite for CodeMetric validation configuration parameters.""" - @patch("galileo.metric.time.time") - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.time.time") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_custom_timeout_value_is_respected( self, mock_config, @@ -1811,7 +1811,7 @@ def test_custom_timeout_value_is_respected( mock_validation_task_result, ) -> None: """Test that Configuration.code_validation_timeout is respected.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration # Set a custom timeout of 30 seconds Configuration.code_validation_timeout = 30.0 @@ -1830,11 +1830,11 @@ def test_custom_timeout_value_is_respected( with pytest.raises(ValidationError, match="Code validation timed out after 30 seconds"): metric.create() - @patch("galileo.metric.time.time") - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.time.time") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_custom_initial_delay_is_used( self, mock_config, @@ -1849,7 +1849,7 @@ def test_custom_initial_delay_is_used( mock_validation_task_result, ) -> None: """Test that Configuration.code_validation_initial_delay is used for first sleep.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration # Set custom initial delay Configuration.code_validation_initial_delay = 2.0 @@ -1881,11 +1881,11 @@ def test_custom_initial_delay_is_used( first_sleep_call = mock_sleep.call_args_list[0] assert first_sleep_call[0][0] == 2.0 - @patch("galileo.metric.time.time") - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.time.time") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_custom_max_delay_caps_backoff( self, mock_config, @@ -1900,7 +1900,7 @@ def test_custom_max_delay_caps_backoff( mock_validation_task_result, ) -> None: """Test that Configuration.code_validation_max_delay caps the exponential backoff.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration # Set custom delays: initial=10, max=15, multiplier=2 (so 10*2=20 > 15, should cap at 15) Configuration.code_validation_initial_delay = 10.0 @@ -1934,11 +1934,11 @@ def test_custom_max_delay_caps_backoff( second_sleep_call = mock_sleep.call_args_list[1] assert second_sleep_call[0][0] == 15.0 # Capped at max_delay - @patch("galileo.metric.time.time") - @patch("galileo.metric.time.sleep") - @patch("galileo.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") - @patch("galileo.metric.validate_code_scorer_scorers_code_validate_post") - @patch("galileo.metric.SplunkAOConfig") + @patch("splunk_ao.metric.time.time") + @patch("splunk_ao.metric.time.sleep") + @patch("splunk_ao.metric.get_validate_code_scorer_task_result_scorers_code_validate_task_id_get") + @patch("splunk_ao.metric.validate_code_scorer_scorers_code_validate_post") + @patch("splunk_ao.metric.SplunkAOConfig") def test_custom_backoff_multiplier_is_applied( self, mock_config, @@ -1953,7 +1953,7 @@ def test_custom_backoff_multiplier_is_applied( mock_validation_task_result, ) -> None: """Test that Configuration.code_validation_backoff_multiplier is applied correctly.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration # Set custom delays: initial=1, max=100, multiplier=3 (so second delay = 1*3=3) Configuration.code_validation_initial_delay = 1.0 @@ -1991,7 +1991,7 @@ def test_custom_backoff_multiplier_is_applied( def test_configuration_defaults_are_correct(self, reset_configuration: None) -> None: """Test that Configuration defaults for code validation are correct.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration assert Configuration.code_validation_timeout == 60.0 assert Configuration.code_validation_initial_delay == 5.0 @@ -2000,7 +2000,7 @@ def test_configuration_defaults_are_correct(self, reset_configuration: None) -> def test_configuration_values_can_be_set(self, reset_configuration: None) -> None: """Test that Configuration values for code validation can be set.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration Configuration.code_validation_timeout = 120.0 Configuration.code_validation_initial_delay = 2.0 @@ -2014,7 +2014,7 @@ def test_configuration_values_can_be_set(self, reset_configuration: None) -> Non def test_configuration_from_env_vars(self, reset_configuration: None, monkeypatch: pytest.MonkeyPatch) -> None: """Test that Configuration values can be set via environment variables.""" - from galileo.configuration import Configuration + from splunk_ao.configuration import Configuration monkeypatch.setenv("SPLUNK_AO_CODE_VALIDATION_TIMEOUT", "90.0") monkeypatch.setenv("SPLUNK_AO_CODE_VALIDATION_INITIAL_DELAY", "3.0") diff --git a/tests/test_metric_types.py b/tests/test_metric_types.py index fa6f3157..e6b989e7 100644 --- a/tests/test_metric_types.py +++ b/tests/test_metric_types.py @@ -12,10 +12,10 @@ import pytest -from galileo.metric import CodeMetric, SplunkAOMetric, LlmMetric, LocalMetric, Metric from galileo.resources.models import OutputTypeEnum, ScorerTypes -from galileo.shared.exceptions import ValidationError from galileo_core.schemas.logging.step import StepType +from splunk_ao.metric import CodeMetric, LlmMetric, LocalMetric, Metric, SplunkAOMetric +from splunk_ao.shared.exceptions import ValidationError class TestLlmMetric: @@ -243,7 +243,7 @@ def test_metric_has_scorers_attribute(self): def test_metric_scorers_is_builtin_scorers(self): """Test that Metric.metrics is a BuiltInMetrics instance and legacy 'scorers' still exists.""" - from galileo.metric import BuiltInMetrics + from splunk_ao.metric import BuiltInMetrics assert isinstance(Metric.metrics, BuiltInMetrics) # Legacy alias should still exist and point to the same instance diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 59393da2..ad722bda 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -5,7 +5,6 @@ import pytest -from galileo.metrics import Metrics, create_custom_llm_metric, delete_metric, get_metrics from galileo.resources.models import ( BucketedMetrics, HTTPValidationError, @@ -22,6 +21,7 @@ from galileo.resources.models.scorer_response import ScorerResponse from galileo.resources.models.scorer_types import ScorerTypes from galileo_core.schemas.logging.step import StepType +from splunk_ao.metrics import Metrics, create_custom_llm_metric, delete_metric, get_metrics FIXED_PROJECT_ID = str(uuid4()) @@ -80,8 +80,8 @@ def _log_records_metrics_response_factory() -> LogRecordsMetricsResponse: class TestMetrics: """Test cases for the Metrics class.""" - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_create_custom_llm_metric_success( self, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -124,8 +124,8 @@ def test_create_custom_llm_metric_success( assert version_request.user_prompt == "Rate the quality of this response" assert create_version_call.kwargs["scorer_id"] == mock_scorer_response.id - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_create_custom_llm_metric_with_custom_parameters( self, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -169,8 +169,8 @@ def test_create_custom_llm_metric_with_custom_parameters( version_request = mock_create_version.sync.call_args.kwargs["body"] assert version_request.user_prompt == "Custom prompt for evaluation" - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_create_custom_llm_metric_scorer_creation_failure(self, mock_create_scorer, mock_create_version) -> None: """Test handling of scorer creation failure.""" # Setup mock to raise exception @@ -185,8 +185,8 @@ def test_create_custom_llm_metric_scorer_creation_failure(self, mock_create_scor # Verify create_version was not called mock_create_version.sync.assert_not_called() - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_create_custom_llm_metric_version_creation_failure( self, mock_create_scorer, mock_create_version, mock_scorer_response ) -> None: @@ -205,9 +205,9 @@ def test_create_custom_llm_metric_version_creation_failure( mock_create_scorer.sync.assert_called_once() mock_create_version.sync.assert_called_once() - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") - @patch("galileo.metrics._logger") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") + @patch("splunk_ao.metrics._logger") def test_create_custom_llm_metric_logging( self, mock_logger, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -224,8 +224,8 @@ def test_create_custom_llm_metric_logging( # Verify logging was called mock_logger.info.assert_called_once_with("Created custom LLM metric: %s", "test_metric") - @patch("galileo.metrics.delete_scorer_scorers_scorer_id_delete") - @patch("galileo.scorers.Scorers.list") + @patch("splunk_ao.metrics.delete_scorer_scorers_scorer_id_delete") + @patch("splunk_ao.scorers.Scorers.list") def test_delete_metric_success(self, mock_list_scorers, mock_delete_scorer, mock_scorer_response) -> None: """Test successful deletion of a metric.""" mock_list_scorers.return_value = [mock_scorer_response] @@ -237,7 +237,7 @@ def test_delete_metric_success(self, mock_list_scorers, mock_delete_scorer, mock scorer_id=mock_scorer_response.id, client=metrics.config.api_client ) - @patch("galileo.scorers.Scorers.list") + @patch("splunk_ao.scorers.Scorers.list") def test_delete_metric_not_found(self, mock_list_scorers) -> None: """Test deleting a metric that does not exist.""" mock_list_scorers.return_value = [] @@ -246,8 +246,8 @@ def test_delete_metric_not_found(self, mock_list_scorers) -> None: with pytest.raises(ValueError, match="Scorer with name test_metric not found."): metrics.delete_metric(name="test_metric") - @patch("galileo.metrics.delete_scorer_scorers_scorer_id_delete") - @patch("galileo.scorers.Scorers.list") + @patch("splunk_ao.metrics.delete_scorer_scorers_scorer_id_delete") + @patch("splunk_ao.scorers.Scorers.list") def test_delete_metric_api_failure(self, mock_list_scorers, mock_delete_scorer, mock_scorer_response) -> None: """Test API failure when deleting a metric.""" mock_list_scorers.return_value = [mock_scorer_response] @@ -261,7 +261,7 @@ def test_delete_metric_api_failure(self, mock_list_scorers, mock_delete_scorer, class TestPublicFunctions: """Test cases for public functions.""" - @patch("galileo.metrics.Metrics") + @patch("splunk_ao.metrics.Metrics") def test_create_custom_llm_metric_function(self, mock_metrics_class) -> None: """Test the public create_custom_llm_metric function.""" # Setup mock @@ -304,7 +304,7 @@ def test_create_custom_llm_metric_function(self, mock_metrics_class) -> None: # Verify the result is returned assert result == mock_result - @patch("galileo.metrics.Metrics") + @patch("splunk_ao.metrics.Metrics") def test_create_custom_llm_metric_function_default_parameters(self, mock_metrics_class) -> None: """Test the public function with default parameters.""" # Setup mock @@ -333,7 +333,7 @@ def test_create_custom_llm_metric_function_default_parameters(self, mock_metrics # Verify the result is returned assert result == mock_result - @patch("galileo.metrics.Metrics") + @patch("splunk_ao.metrics.Metrics") def test_delete_metric_function(self, mock_metrics_class) -> None: """Test the public delete_metric function.""" mock_metrics_instance = Mock() @@ -347,8 +347,8 @@ def test_delete_metric_function(self, mock_metrics_class) -> None: class TestEdgeCases: """Test edge cases and boundary conditions.""" - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_empty_string_parameters( self, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -378,8 +378,8 @@ def test_empty_string_parameters( version_request = mock_create_version.sync.call_args.kwargs["body"] assert version_request.user_prompt == "" - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_large_num_judges( self, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -403,8 +403,8 @@ def test_large_num_judges( version_request = mock_create_version.sync.call_args.kwargs["body"] assert version_request.user_prompt == "Test prompt" - @patch("galileo.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") - @patch("galileo.metrics.create_scorers_post") + @patch("splunk_ao.metrics.create_llm_scorer_version_scorers_scorer_id_version_llm_post") + @patch("splunk_ao.metrics.create_scorers_post") def test_long_tag_list( self, mock_create_scorer, mock_create_version, mock_scorer_response, mock_scorer_version_response ) -> None: @@ -429,7 +429,7 @@ def test_long_tag_list( class TestGetMetrics: - @patch("galileo.metrics.query_metrics_projects_project_id_metrics_search_post.sync") + @patch("splunk_ao.metrics.query_metrics_projects_project_id_metrics_search_post.sync") def test_successful_call(self, mock_api_call): mock_response = _log_records_metrics_response_factory() mock_api_call.return_value = mock_response @@ -443,7 +443,7 @@ def test_successful_call(self, mock_api_call): assert FIXED_PROJECT_ID in mock_api_call.call_args[1]["project_id"] assert response == mock_response - @patch("galileo.metrics.query_metrics_projects_project_id_metrics_search_post.sync") + @patch("splunk_ao.metrics.query_metrics_projects_project_id_metrics_search_post.sync") def test_api_failure_raises_value_error(self, mock_api_call): mock_api_call.return_value = None @@ -455,7 +455,7 @@ def test_api_failure_raises_value_error(self, mock_api_call): mock_api_call.assert_called_once() - @patch("galileo.metrics.query_metrics_projects_project_id_metrics_search_post.sync") + @patch("splunk_ao.metrics.query_metrics_projects_project_id_metrics_search_post.sync") def test_http_validation_error_raises_exception(self, mock_api_call): detail = [ValidationError(loc=["body", "project_id"], msg="value is not a valid uuid", type_="type_error.uuid")] mock_api_call.return_value = HTTPValidationError(detail=detail) @@ -466,7 +466,7 @@ def test_http_validation_error_raises_exception(self, mock_api_call): with pytest.raises(ValueError, match=re.escape(str(detail))): get_metrics(project_id=FIXED_PROJECT_ID, start_time=start_time, end_time=end_time) - @patch("galileo.metrics.query_metrics_projects_project_id_metrics_search_post.sync") + @patch("splunk_ao.metrics.query_metrics_projects_project_id_metrics_search_post.sync") def test_passes_all_parameters_correctly(self, mock_api_call): mock_api_call.return_value = _log_records_metrics_response_factory() diff --git a/tests/test_middleware_tracing.py b/tests/test_middleware_tracing.py index f230fbf5..3cfee47a 100644 --- a/tests/test_middleware_tracing.py +++ b/tests/test_middleware_tracing.py @@ -6,10 +6,10 @@ from fastapi import FastAPI from fastapi.testclient import TestClient -from galileo.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER -from galileo.decorator import _parent_id_context, _trace_id_context -from galileo.logger import SplunkAOLogger -from galileo.middleware import TracingMiddleware, get_request_logger +from splunk_ao.constants.tracing import PARENT_ID_HEADER, TRACE_ID_HEADER +from splunk_ao.decorator import _parent_id_context, _trace_id_context +from splunk_ao.logger import SplunkAOLogger +from splunk_ao.middleware import TracingMiddleware, get_request_logger from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -64,9 +64,9 @@ def client(app): return TestClient(app) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_middleware_extracts_headers( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -123,9 +123,9 @@ def test_middleware_extracts_headers( assert data["span_id"] == parent_id -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_middleware_handles_missing_headers( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -143,9 +143,9 @@ def test_middleware_handles_missing_headers( assert data["span_id"] is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_middleware_handles_partial_headers( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -172,9 +172,9 @@ def test_middleware_handles_partial_headers( assert data["span_id"] is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_context_cleanup_after_request( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -201,9 +201,9 @@ def test_context_cleanup_after_request( assert data2["parent_id"] is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_get_request_logger_when_parent_id_equals_trace_id( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -233,9 +233,9 @@ def test_get_request_logger_when_parent_id_equals_trace_id( assert data["span_id"] is None -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_mismatched_trace_and_span_ids( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, client: TestClient ): @@ -267,13 +267,13 @@ def test_mismatched_trace_and_span_ids( assert data["span_id"] == parent_id -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.LogStreams") def test_invalid_uuid_headers_raise_exception( mock_logstreams_client: Mock, mock_projects_client: Mock, app: FastAPI, client: TestClient ): """Test that invalid UUID headers raise SplunkAOLoggerException.""" - from galileo.exceptions import SplunkAOLoggerException + from splunk_ao.exceptions import SplunkAOLoggerException setup_mock_projects_client(mock_projects_client) setup_mock_logstreams_client(mock_logstreams_client) diff --git a/tests/test_namespace_compatibility.py b/tests/test_namespace_compatibility.py new file mode 100644 index 00000000..56c725d1 --- /dev/null +++ b/tests/test_namespace_compatibility.py @@ -0,0 +1,70 @@ +import importlib +import importlib.util +import sys +from collections.abc import Generator + +import pytest + + +def _clear_legacy_modules() -> None: + for module_name in list(sys.modules): + if module_name == "galileo" or module_name.startswith("galileo."): + sys.modules.pop(module_name) + + +@pytest.fixture(autouse=True) +def restore_legacy_modules() -> Generator[None, None, None]: + previous_modules = { + module_name: module + for module_name, module in sys.modules.items() + if module_name == "galileo" or module_name.startswith("galileo.") + } + + yield + + _clear_legacy_modules() + sys.modules.update(previous_modules) + + +def test_splunk_ao_import_smoke() -> None: + module = importlib.import_module("splunk_ao") + + assert module.__version__ + assert hasattr(module, "galileo_context") + assert importlib.import_module("splunk_ao.openai") + assert importlib.import_module("splunk_ao.logger") + + +def test_legacy_galileo_import_shim_warns() -> None: + _clear_legacy_modules() + + with pytest.warns(DeprecationWarning, match="use 'splunk_ao' instead"): + module = importlib.import_module("galileo") + + assert hasattr(module, "galileo_context") + + +def test_protected_generated_resource_imports_remain_available() -> None: + _clear_legacy_modules() + + with pytest.warns(DeprecationWarning, match="use 'splunk_ao' instead"): + resources = importlib.import_module("galileo.resources") + + assert resources is not None + + +def test_generated_resource_dependency_shims_remain_available() -> None: + _clear_legacy_modules() + + with pytest.warns(DeprecationWarning, match="use 'splunk_ao' instead"): + exceptions = importlib.import_module("galileo.exceptions") + headers_data = importlib.import_module("galileo.utils.headers_data") + + assert hasattr(exceptions, "NotFoundError") + assert hasattr(headers_data, "get_sdk_header") + + +def test_namespace_package_discovery_paths() -> None: + assert importlib.util.find_spec("splunk_ao") is not None + assert importlib.util.find_spec("galileo") is not None + assert importlib.util.find_spec("galileo.resources") is not None diff --git a/tests/test_openai.py b/tests/test_openai.py index 9dd591db..b6f1aaa5 100644 --- a/tests/test_openai.py +++ b/tests/test_openai.py @@ -7,9 +7,9 @@ from openai.types.chat import ChatCompletionChunk from openai.types.responses import ResponseCompletedEvent -from galileo import Message, MessageRole, galileo_context, log -from galileo.openai import OpenAISplunkAO, openai from galileo_core.schemas.logging.span import LlmSpan, WorkflowSpan +from splunk_ao import Message, MessageRole, galileo_context, log +from splunk_ao.openai import OpenAIGalileo, openai from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client from tests.testutils.streaming import EventStream, ResponsesEventStream @@ -30,9 +30,9 @@ def openai_incorrect_api_key_error() -> bytes: @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_basic_openai_call( mock_traces_client: Mock, mock_projects_client: Mock, @@ -46,7 +46,7 @@ def test_basic_openai_call( openai_create.return_value = create_chat_completion galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() chat_completion = openai.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], @@ -94,9 +94,9 @@ def test_basic_openai_call( @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_streamed_openai_call( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, openai_create ) -> None: @@ -109,7 +109,7 @@ def test_streamed_openai_call( ) galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() stream = openai.chat.completions.create( messages=[{"role": "user", "content": "Say this is a test"}], model="gpt-3.5-turbo", stream=True @@ -142,9 +142,9 @@ def test_streamed_openai_call( @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_openai_api_calls_as_parent_span( mock_traces_client: Mock, mock_projects_client: Mock, @@ -159,7 +159,7 @@ def test_openai_api_calls_as_parent_span( # we want reset context and enable tracing for openai plugin galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() @log() def call_openai(model: str = "gpt-3.5-turbo"): @@ -195,9 +195,9 @@ def call_openai(model: str = "gpt-3.5-turbo"): "openai.resources.chat.Completions.create", side_effect=openai.OpenAIError("The api_key client option must be set either"), ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_openai_error_trace( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, openai_create ) -> None: @@ -207,7 +207,7 @@ def test_openai_error_trace( # we want reset context and enable tracing for openai plugin galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() def call_openai(model: str = "gpt-3.5-turbo"): chat_completion = openai.chat.completions.create( @@ -227,9 +227,9 @@ def call_openai(model: str = "gpt-3.5-turbo"): @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_openai_error_trace_( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, openai_create ) -> None: @@ -244,7 +244,7 @@ def test_openai_error_trace_( # we want reset context and enable tracing for openai plugin galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() def call_openai(model: str = "gpt-3.5-turbo"): chat_completion = openai.chat.completions.create( @@ -272,9 +272,9 @@ def call_openai(model: str = "gpt-3.5-turbo"): "openai.resources.chat.Completions.create", side_effect=openai.OpenAIError("The api_key client option must be set either"), ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_client_fails_because_openai_error_trace_no_exp( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, openai_create ) -> None: @@ -284,7 +284,7 @@ def test_client_fails_because_openai_error_trace_no_exp( # we want reset context and enable tracing for openai plugin galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() @log def call_openai(model: str = "gpt-3.5-turbo"): @@ -308,9 +308,9 @@ def call_openai(model: str = "gpt-3.5-turbo"): @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams", side_effect=Exception("error")) -@patch("galileo.logger.logger.Projects", side_effect=Exception("error")) -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams", side_effect=Exception("error")) +@patch("splunk_ao.logger.logger.Projects", side_effect=Exception("error")) +@patch("splunk_ao.logger.logger.Traces") def test_galileo_api_client_transport_error_not_blocking_user_code( mock_traces_client: Mock, mock_projects_client: Mock, @@ -329,7 +329,7 @@ def test_galileo_api_client_transport_error_not_blocking_user_code( openai_create.return_value = create_chat_completion # we want reset context and enable tracing for openai plugin galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() @log() def call_openai(model: str = "gpt-3.5-turbo"): @@ -348,9 +348,9 @@ def call_openai(model: str = "gpt-3.5-turbo"): @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_openai_calls_in_active_trace( mock_traces_client: Mock, mock_projects_client: Mock, @@ -364,7 +364,7 @@ def test_openai_calls_in_active_trace( openai_create.return_value = create_chat_completion galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() logger = galileo_context.get_logger_instance() logger.start_trace("test trace") @@ -386,9 +386,9 @@ def test_openai_calls_in_active_trace( @patch("openai.resources.chat.Completions.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_chat_completions_multiple_messages( mock_traces_client: Mock, mock_projects_client: Mock, @@ -403,7 +403,7 @@ def test_chat_completions_multiple_messages( openai_create.return_value = create_chat_completion galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() input_messages = [ {"role": "user", "content": "What's the weather like today?"}, @@ -447,9 +447,9 @@ def test_chat_completions_multiple_messages( @patch("openai.resources.responses.Responses.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_basic_responses_api_call( mock_traces_client: Mock, mock_projects_client: Mock, @@ -463,7 +463,7 @@ def test_basic_responses_api_call( openai_create.return_value = create_responses_response galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() response = openai.responses.create(input="Say this is a test", model="gpt-4o") @@ -488,9 +488,9 @@ def test_basic_responses_api_call( @patch("openai.resources.responses.Responses.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_responses_api_with_tools( mock_traces_client: Mock, mock_projects_client: Mock, @@ -504,7 +504,7 @@ def test_responses_api_with_tools( openai_create.return_value = create_responses_response_with_tools galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() openai.responses.create( input="What's the weather like?", @@ -551,9 +551,9 @@ def test_responses_api_with_tools( @patch("openai.resources.responses.Responses.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_responses_api_multiple_messages( mock_traces_client: Mock, mock_projects_client: Mock, @@ -568,7 +568,7 @@ def test_responses_api_multiple_messages( openai_create.return_value = create_responses_response galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() input_messages = [ {"role": "user", "content": "What's the weather like today?"}, @@ -613,9 +613,9 @@ def test_responses_api_multiple_messages( @patch("openai.resources.responses.Responses.create") -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") def test_responses_api_streaming( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, openai_create ) -> None: @@ -631,7 +631,7 @@ def test_responses_api_streaming( ) galileo_context.reset() - OpenAISplunkAO().register_tracing() + OpenAIGalileo().register_tracing() stream = openai.responses.create(input="Say hello", model="gpt-4o", stream=True) diff --git a/tests/test_openai_agents.py b/tests/test_openai_agents.py index a3a230e5..d4d5ef36 100644 --- a/tests/test_openai_agents.py +++ b/tests/test_openai_agents.py @@ -18,10 +18,10 @@ from pydantic import BaseModel from pytest import MonkeyPatch, mark -from galileo.handlers.openai_agents import SplunkAOTracingProcessor -from galileo.logger.logger import SplunkAOLogger -from galileo.utils.openai_agents import _extract_llm_data, _parse_usage from galileo_core.schemas.logging.span import LlmSpan, ToolSpan +from splunk_ao.handlers.openai_agents import SplunkAOTracingProcessor +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.utils.openai_agents import _extract_llm_data, _parse_usage from tests.testutils.setup import setup_mock_logstreams_client, setup_mock_projects_client, setup_mock_traces_client @@ -71,9 +71,9 @@ async def homework_guardrail(ctx, agent, input_data): decode_compressed_response=True, record_mode=vcr.mode.NEW_EPISODES, ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_complex_agent( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: MonkeyPatch ) -> None: @@ -102,9 +102,9 @@ async def test_complex_agent( decode_compressed_response=True, record_mode=vcr.mode.NEW_EPISODES, ) -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_simple_agent( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: MonkeyPatch ) -> None: @@ -196,9 +196,9 @@ def _find_tool_spans(spans): @mark.asyncio -@patch("galileo.logger.logger.LogStreams") -@patch("galileo.logger.logger.Projects") -@patch("galileo.logger.logger.Traces") +@patch("splunk_ao.logger.logger.LogStreams") +@patch("splunk_ao.logger.logger.Projects") +@patch("splunk_ao.logger.logger.Traces") async def test_pre_built_tools_multiple_types( mock_traces_client: Mock, mock_projects_client: Mock, mock_logstreams_client: Mock, monkeypatch: MonkeyPatch ) -> None: diff --git a/tests/test_openai_agents_utils.py b/tests/test_openai_agents_utils.py index 617cf96e..7ef33611 100644 --- a/tests/test_openai_agents_utils.py +++ b/tests/test_openai_agents_utils.py @@ -17,7 +17,8 @@ ) from agents.tracing import ResponseSpanData -from galileo.utils.openai_agents import ( +from galileo_core.schemas.logging.span import ToolSpan, WorkflowSpan +from splunk_ao.utils.openai_agents import ( SplunkAOCustomSpan, _extract_llm_data, _extract_tool_data, @@ -26,7 +27,6 @@ _map_span_type, _parse_usage, ) -from galileo_core.schemas.logging.span import ToolSpan, WorkflowSpan class TestParseUsage: diff --git a/tests/test_openai_extractors.py b/tests/test_openai_extractors.py index 00678ed5..bbb5cfb8 100644 --- a/tests/test_openai_extractors.py +++ b/tests/test_openai_extractors.py @@ -7,7 +7,7 @@ import pytest -from galileo.openai.extractors import _parse_usage +from splunk_ao.openai.extractors import _parse_usage class TestParseUsage: diff --git a/tests/test_otel.py b/tests/test_otel.py index aad2b4fc..5d5e9de9 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -6,7 +6,8 @@ import pytest from pydantic import SecretStr -from galileo.decorator import ( +from galileo_core.schemas.logging.span import ToolSpan +from splunk_ao.decorator import ( _dataset_input_context, _dataset_metadata_context, _dataset_output_context, @@ -16,7 +17,7 @@ _session_id_context, galileo_dataset_context, ) -from galileo.otel import ( +from splunk_ao.otel import ( _TRACE_PROVIDER_CONTEXT_VAR, INSTALL_ERR_MSG, OTEL_AVAILABLE, @@ -25,13 +26,12 @@ _set_tool_span_attributes, start_galileo_span, ) -from galileo_core.schemas.logging.span import ToolSpan if OTEL_AVAILABLE: - from galileo.otel import _set_workflow_span_attributes, start_galileo_span from galileo_core.schemas.logging.llm import Message, MessageRole from galileo_core.schemas.logging.span import WorkflowSpan from galileo_core.schemas.shared.document import Document + from splunk_ao.otel import _set_workflow_span_attributes, start_galileo_span class TestSplunkAOOTLPExporter: @@ -56,7 +56,7 @@ def clear_env_vars(self): @pytest.fixture def mock_config(self): """Create a mock config with default values.""" - with patch("galileo.otel.SplunkAOConfig.get") as mock_config_get: + with patch("splunk_ao.otel.SplunkAOConfig.get") as mock_config_get: config = Mock() config.api_url = "https://api.galileo.ai" config.api_key = SecretStr("test-key") @@ -64,7 +64,7 @@ def mock_config(self): yield config @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) def test_init_and_parameter_priority(self, mock_otlp_init, mock_config, clear_env_vars): """Test initialization with params, env vars, and their priority.""" # Test with explicit params @@ -84,7 +84,7 @@ def test_init_and_parameter_priority(self, mock_otlp_init, mock_config, clear_en assert exporter.project == "param-project" # Param wins over env @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) def test_init_with_env_variables(self, mock_otlp_init, mock_config, clear_env_vars): """Test initialization using environment variables.""" with patch.dict(os.environ, {"SPLUNK_AO_PROJECT": "env-project", "SPLUNK_AO_LOG_STREAM": "env-logstream"}): @@ -93,7 +93,7 @@ def test_init_with_env_variables(self, mock_otlp_init, mock_config, clear_env_va assert exporter.logstream == "env-logstream" @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) def test_init_uses_default_project(self, mock_otlp_init, mock_config, clear_env_vars): """Test default project name is used when no project is provided.""" SplunkAOOTLPExporter() @@ -103,7 +103,7 @@ def test_init_uses_default_project(self, mock_otlp_init, mock_config, clear_env_ assert call_kwargs["headers"]["logstream"] == "default" @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) @pytest.mark.parametrize( "api_url,expected_endpoint", [ @@ -133,8 +133,8 @@ class TestSplunkAOSpanProcessor: def mock_processor_setup(self): """Set up common mocks for span processor tests.""" with ( - patch("galileo.otel.BatchSpanProcessor") as mock_batch_processor, - patch("galileo.otel.SplunkAOOTLPExporter") as mock_exporter_class, + patch("splunk_ao.otel.BatchSpanProcessor") as mock_batch_processor, + patch("splunk_ao.otel.SplunkAOOTLPExporter") as mock_exporter_class, ): mock_exporter_instance = Mock() mock_processor_instance = Mock() @@ -167,7 +167,7 @@ def test_init_with_default_processor(self, mock_processor_setup): assert processor.processor == mocks["mock_processor_instance"] @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.SplunkAOOTLPExporter") + @patch("splunk_ao.otel.SplunkAOOTLPExporter") def test_init_with_custom_processor(self, mock_exporter_class): """Test initialization with custom span processor class.""" mock_exporter_instance = Mock() @@ -253,7 +253,7 @@ def test_init_passes_all_parameters_to_exporter(self, mock_processor_setup): class TestOTelUnavailable: """Test behavior when OpenTelemetry is not available.""" - @patch("galileo.otel.OTEL_AVAILABLE", False) + @patch("splunk_ao.otel.OTEL_AVAILABLE", False) def test_galileo_span_processor_raises_import_error_when_otel_unavailable(self): """Test that SplunkAOSpanProcessor raises ImportError when OpenTelemetry is not available.""" with pytest.raises(ImportError, match=re.escape(INSTALL_ERR_MSG)): @@ -271,9 +271,9 @@ class TestOTelIntegration: """Integration tests for OpenTelemetry functionality.""" @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.BatchSpanProcessor") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) - @patch("galileo.otel.SplunkAOConfig.get") + @patch("splunk_ao.otel.BatchSpanProcessor") + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.SplunkAOConfig.get") def test_exporter_and_processor_integration(self, mock_config_get, mock_otlp_init, mock_batch_processor): """Test that SplunkAOSpanProcessor correctly integrates with SplunkAOOTLPExporter.""" mock_batch_instance = Mock() @@ -313,8 +313,8 @@ def reset_decorator_context(self): def mock_processor_deps(self): """Mock dependencies for processor tests.""" with ( - patch("galileo.otel.BatchSpanProcessor") as mock_batch, - patch("galileo.otel.SplunkAOOTLPExporter") as mock_exp, + patch("splunk_ao.otel.BatchSpanProcessor") as mock_batch, + patch("splunk_ao.otel.SplunkAOOTLPExporter") as mock_exp, ): mock_exp.return_value = Mock() mock_batch.return_value = Mock() @@ -324,8 +324,8 @@ def mock_processor_deps(self): def mock_exporter(self): """Create a mock exporter for export tests.""" with ( - patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None), - patch("galileo.otel.SplunkAOConfig.get") as mock_config_get, + patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None), + patch("splunk_ao.otel.SplunkAOConfig.get") as mock_config_get, ): config = Mock() config.api_url = "https://api.galileo.ai" @@ -334,8 +334,8 @@ def mock_exporter(self): yield SplunkAOOTLPExporter(project="test-project", logstream="test-logstream") @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None) - @patch("galileo.otel.SplunkAOConfig.get") + @patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None) + @patch("splunk_ao.otel.SplunkAOConfig.get") def test_exporter_context_vars_and_override(self, mock_config_get, mock_otlp_init, reset_decorator_context): """Test exporter reads from context vars and params override them.""" mock_config = Mock() @@ -399,10 +399,10 @@ def test_processor_on_start_sets_span_attributes(self, mock_processor_deps, rese # Then: experiment_id is set and logstream is excluded (experiment takes priority) assert mock_span.set_attribute.call_count == 3 actual_calls = {(args[0], args[1]) for args, _ in mock_span.set_attribute.call_args_list} - assert ("galileo.project.name", "test-project") in actual_calls - assert ("galileo.session.id", "test-session") in actual_calls - assert ("galileo.experiment.id", "test-experiment") in actual_calls - assert ("galileo.logstream.name", "test-logstream") not in actual_calls + assert ("splunk_ao.project.name", "test-project") in actual_calls + assert ("splunk_ao.session.id", "test-session") in actual_calls + assert ("splunk_ao.experiment.id", "test-experiment") in actual_calls + assert ("splunk_ao.logstream.name", "test-logstream") not in actual_calls # Given: context vars are None, falling back to env vars _log_stream_context.set(None) @@ -419,21 +419,21 @@ def test_processor_on_start_sets_span_attributes(self, mock_processor_deps, rese # Then: project and logstream are set from env var fallbacks assert mock_span2.set_attribute.call_count == 2 actual_calls = {(args[0], args[1]) for args, _ in mock_span2.set_attribute.call_args_list} - assert ("galileo.project.name", "test-project") in actual_calls + assert ("splunk_ao.project.name", "test-project") in actual_calls # Falls back to SPLUNK_AO_LOG_STREAM env var - assert ("galileo.logstream.name", "test-log-stream") in actual_calls + assert ("splunk_ao.logstream.name", "test-log-stream") in actual_calls finally: monkeypatch.undo() @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.export") - @patch("galileo.otel.Resource") + @patch("splunk_ao.otel.OTLPSpanExporter.export") + @patch("splunk_ao.otel.Resource") def test_exporter_export_merges_resource_attributes(self, mock_resource_class, mock_parent_export): """Test export merges Galileo attributes into resource, handles partial/no attributes.""" # Create a real exporter with mocked dependencies with ( - patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None), - patch("galileo.otel.SplunkAOConfig.get") as mock_config_get, + patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None), + patch("splunk_ao.otel.SplunkAOConfig.get") as mock_config_get, ): config = Mock() config.api_url = "https://api.galileo.ai" @@ -448,10 +448,10 @@ def test_exporter_export_merges_resource_attributes(self, mock_resource_class, m # Given: a span with experiment_id present (logstream should be excluded) mock_span = Mock() mock_span.attributes = { - "galileo.project.name": "span-project", - "galileo.logstream.name": "span-logstream", - "galileo.session.id": "span-session", - "galileo.experiment.id": "span-experiment", + "splunk_ao.project.name": "span-project", + "splunk_ao.logstream.name": "span-logstream", + "splunk_ao.session.id": "span-session", + "splunk_ao.experiment.id": "span-experiment", "other.attribute": "value", } mock_merged_resource = Mock() @@ -464,12 +464,12 @@ def test_exporter_export_merges_resource_attributes(self, mock_resource_class, m # Then: resource was created with Galileo attributes (logstream excluded when experiment present) call_args = mock_resource_class.call_args[0][0] - assert "galileo.project.name" in call_args - assert call_args["galileo.project.name"] == "span-project" + assert "splunk_ao.project.name" in call_args + assert call_args["splunk_ao.project.name"] == "span-project" # Then: logstream is not included because experiment takes priority - assert "galileo.logstream.name" not in call_args - assert "galileo.session.id" in call_args - assert "galileo.experiment.id" in call_args + assert "splunk_ao.logstream.name" not in call_args + assert "splunk_ao.session.id" in call_args + assert "splunk_ao.experiment.id" in call_args assert "other.attribute" not in call_args # Verify resource was merged and span._resource was updated @@ -648,7 +648,7 @@ class TestWorkflowSpanAttributes: @pytest.fixture def mock_dependencies(self): """Set up mocks for testing workflow span attributes.""" - with patch("galileo.otel.trace") as mock_trace_module, patch("galileo.otel.json") as mock_json_module: + with patch("splunk_ao.otel.trace") as mock_trace_module, patch("splunk_ao.otel.json") as mock_json_module: mock_span = Mock() mock_json_module.dumps.return_value = '"test"' yield {"span": mock_span, "trace": mock_trace_module, "json": mock_json_module} @@ -753,7 +753,7 @@ def test_workflow_span_in_start_galileo_span(self, mock_dependencies): mock_trace_provider.get_tracer.return_value = mock_tracer # Patch get_tracer_provider to return our mock - with patch("galileo.otel.trace.get_tracer_provider", return_value=mock_trace_provider): + with patch("splunk_ao.otel.trace.get_tracer_provider", return_value=mock_trace_provider): # When: using start_galileo_span with WorkflowSpan with start_galileo_span(workflow_span): pass @@ -782,8 +782,8 @@ def reset_dataset_context(self): def mock_processor_deps(self): """Mock dependencies for processor tests.""" with ( - patch("galileo.otel.BatchSpanProcessor") as mock_batch, - patch("galileo.otel.SplunkAOOTLPExporter") as mock_exp, + patch("splunk_ao.otel.BatchSpanProcessor") as mock_batch, + patch("splunk_ao.otel.SplunkAOOTLPExporter") as mock_exp, ): mock_exp.return_value = Mock() mock_batch.return_value = Mock() @@ -862,21 +862,21 @@ def test_processor_on_start_sets_dataset_attributes(self, mock_processor_deps, r # Then: dataset attributes are set on the span actual_calls = {(args[0], args[1]) for args, _ in mock_span.set_attribute.call_args_list} - assert ("galileo.dataset.input", "input question") in actual_calls - assert ("galileo.dataset.output", "expected answer") in actual_calls - assert ("galileo.dataset.metadata", json.dumps({"source": "test_dataset"})) in actual_calls + assert ("splunk_ao.dataset.input", "input question") in actual_calls + assert ("splunk_ao.dataset.output", "expected answer") in actual_calls + assert ("splunk_ao.dataset.metadata", json.dumps({"source": "test_dataset"})) in actual_calls @pytest.mark.skipif(not OTEL_AVAILABLE, reason="OpenTelemetry not available") - @patch("galileo.otel.OTLPSpanExporter.export") - @patch("galileo.otel.Resource") + @patch("splunk_ao.otel.OTLPSpanExporter.export") + @patch("splunk_ao.otel.Resource") def test_exporter_export_merges_dataset_attributes( self, mock_resource_class, mock_parent_export, reset_dataset_context ): """Test that export merges dataset attributes from span into resource.""" # Given: an exporter with mocked dependencies with ( - patch("galileo.otel.OTLPSpanExporter.__init__", return_value=None), - patch("galileo.otel.SplunkAOConfig.get") as mock_config_get, + patch("splunk_ao.otel.OTLPSpanExporter.__init__", return_value=None), + patch("splunk_ao.otel.SplunkAOConfig.get") as mock_config_get, ): config = Mock() config.api_url = "https://api.galileo.ai" @@ -890,11 +890,11 @@ def test_exporter_export_merges_dataset_attributes( # Given: a span with dataset attributes (set during on_start) mock_span = Mock() mock_span.attributes = { - "galileo.project.name": "test-project", - "galileo.logstream.name": "test-logstream", - "galileo.dataset.input": "test input", - "galileo.dataset.output": "expected output", - "galileo.dataset.metadata": json.dumps({"key": "value"}), + "splunk_ao.project.name": "test-project", + "splunk_ao.logstream.name": "test-logstream", + "splunk_ao.dataset.input": "test input", + "splunk_ao.dataset.output": "expected output", + "splunk_ao.dataset.metadata": json.dumps({"key": "value"}), } mock_merged_resource = Mock() mock_span.resource = Mock() @@ -907,9 +907,9 @@ def test_exporter_export_merges_dataset_attributes( # Then: Resource is created with dataset attributes resource_call_kwargs = mock_resource_class.call_args[0][0] - assert resource_call_kwargs["galileo.dataset.input"] == "test input" - assert resource_call_kwargs["galileo.dataset.output"] == "expected output" - assert resource_call_kwargs["galileo.dataset.metadata"] == json.dumps({"key": "value"}) + assert resource_call_kwargs["splunk_ao.dataset.input"] == "test input" + assert resource_call_kwargs["splunk_ao.dataset.output"] == "expected output" + assert resource_call_kwargs["splunk_ao.dataset.metadata"] == json.dumps({"key": "value"}) # Then: resource was merged into the span mock_span.resource.merge.assert_called_once_with(mock_new_resource) diff --git a/tests/test_project.py b/tests/test_project.py index f6fec9b5..edf8d301 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -4,10 +4,10 @@ import pytest -from galileo.collaborator import Collaborator, CollaboratorRole -from galileo.project import Project -from galileo.shared.base import SyncState -from galileo.shared.exceptions import APIError, ValidationError +from splunk_ao.collaborator import Collaborator, CollaboratorRole +from splunk_ao.project import Project +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.exceptions import APIError, ValidationError class TestProjectInitialization: @@ -30,7 +30,7 @@ def test_init_without_name_raises_validation_error(self, reset_configuration: No class TestProjectCreate: """Test suite for Project.create() method.""" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_create_persists_project_to_api( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -45,7 +45,7 @@ def test_create_persists_project_to_api( assert project.id == mock_project.id assert project.is_synced() - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_create_handles_api_failure(self, mock_projects_class: MagicMock, reset_configuration: None) -> None: """Test create() handles API failures and sets state correctly.""" mock_service = MagicMock() @@ -64,7 +64,7 @@ class TestProjectGet: """Test suite for Project.get() class method.""" @pytest.mark.parametrize("lookup_key,lookup_value", [("name", "Test Project"), ("id", "test-project-id-123")]) - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_get_returns_project( self, mock_projects_class: MagicMock, @@ -85,7 +85,7 @@ def test_get_returns_project( assert project is not None assert project.is_synced() - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_get_returns_none_when_not_found(self, mock_projects_class: MagicMock, reset_configuration: None) -> None: """Test get() returns None when project is not found.""" mock_service = MagicMock() @@ -96,7 +96,7 @@ def test_get_returns_none_when_not_found(self, mock_projects_class: MagicMock, r assert project is None - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_get_raises_error_for_api_failure(self, mock_projects_class: MagicMock, reset_configuration: None) -> None: """Test get() wraps API errors in APIError.""" mock_service = MagicMock() @@ -110,7 +110,7 @@ def test_get_raises_error_for_api_failure(self, mock_projects_class: MagicMock, class TestProjectList: """Test suite for Project.list() class method.""" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_list_returns_all_projects(self, mock_projects_class: MagicMock, reset_configuration: None) -> None: """Test list() returns a list of synced project instances.""" mock_service = MagicMock() @@ -140,7 +140,7 @@ def test_list_returns_all_projects(self, mock_projects_class: MagicMock, reset_c class TestProjectSave: """Test suite for Project.save() method.""" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_save_local_only_delegates_to_create( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -158,7 +158,7 @@ def test_save_local_only_delegates_to_create( assert result.id == mock_project.id assert result.is_synced() - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_save_synced_is_noop( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -197,9 +197,9 @@ def test_save_without_id_raises_value_error(self, reset_configuration: None) -> with pytest.raises(ValueError, match="Project ID is not set"): project.save() - @patch("galileo.project.SplunkAOConfig") - @patch("galileo.project.update_project_projects_project_id_put") - @patch("galileo.project.Projects") + @patch("splunk_ao.project.SplunkAOConfig") + @patch("splunk_ao.project.update_project_projects_project_id_put") + @patch("splunk_ao.project.Projects") def test_save_dirty_calls_update_and_syncs_attributes( self, mock_projects_class: MagicMock, @@ -251,7 +251,7 @@ def test_save_dirty_calls_update_and_syncs_attributes( assert result.bookmark == mock_project.bookmark assert result.permissions == mock_project.permissions - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_save_failed_sync_raises_value_error( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -267,9 +267,9 @@ def test_save_failed_sync_raises_value_error( with pytest.raises(ValueError, match="FAILED_SYNC"): project.save() - @patch("galileo.project.SplunkAOConfig") - @patch("galileo.project.update_project_projects_project_id_put") - @patch("galileo.project.Projects") + @patch("splunk_ao.project.SplunkAOConfig") + @patch("splunk_ao.project.update_project_projects_project_id_put") + @patch("splunk_ao.project.Projects") def test_save_handles_api_failure( self, mock_projects_class: MagicMock, @@ -299,7 +299,7 @@ def test_save_handles_api_failure( class TestProjectDirtyTracking: """Test suite for Project dirty-tracking via __setattr__.""" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_dirty_tracking_transitions_on_name_change( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -318,7 +318,7 @@ def test_dirty_tracking_transitions_on_name_change( assert project.is_dirty() assert project.name == "A Completely New Name" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_dirty_tracking_noop_on_same_value( self, mock_projects_class: MagicMock, reset_configuration: None, mock_project: MagicMock ) -> None: @@ -361,7 +361,7 @@ def test_repr_representation(self, reset_configuration: None) -> None: class TestProjectCollaborators: """Test suite for Project collaborator management methods.""" - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_add_update_remove_collaborator( self, mock_projects_class: MagicMock, @@ -387,7 +387,7 @@ def test_add_update_remove_collaborator( project.remove_collaborator(user_id=mock_collaborator.user_id) mock_service.unshare_project_with_user.assert_called_once() - @patch("galileo.project.Projects") + @patch("splunk_ao.project.Projects") def test_collaborators_property_returns_same_as_list_method( self, mock_projects_class: MagicMock, @@ -529,7 +529,7 @@ def test_collaborator_to_dict_with_none_values( assert result["last_name"] is None assert result["permissions"] is None - @patch("galileo.collaborator.Projects") + @patch("splunk_ao.collaborator.Projects") def test_collaborator_update_error_path( self, mock_projects_class: MagicMock, reset_configuration: None, mock_collaborator: MagicMock ) -> None: @@ -548,7 +548,7 @@ def test_collaborator_update_error_path( with pytest.raises(Exception, match="API Error"): collab.update(role=CollaboratorRole.EDITOR) - @patch("galileo.collaborator.Projects") + @patch("splunk_ao.collaborator.Projects") def test_collaborator_remove_error_path( self, mock_projects_class: MagicMock, reset_configuration: None, mock_collaborator: MagicMock ) -> None: diff --git a/tests/test_projects.py b/tests/test_projects.py index b259e388..e83dd3f7 100644 --- a/tests/test_projects.py +++ b/tests/test_projects.py @@ -4,8 +4,8 @@ import httpx import pytest -from galileo.projects import Projects, ProjectsAPIException, delete_project from galileo.resources.models.project_type import ProjectType +from splunk_ao.projects import Projects, ProjectsAPIException, delete_project @pytest.fixture(autouse=True) @@ -15,7 +15,7 @@ def reset_env_vars() -> None: class TestProjects: - @patch("galileo.projects.get_all_projects_projects_all_get") + @patch("splunk_ao.projects.get_all_projects_projects_all_get") def test_get_all_projects_projects_all_get_exc(self, get_all_projects_projects_all_get) -> None: """Test that list raises ValueError when API call fails.""" get_all_projects_projects_all_get.sync.side_effect = ValueError("unable to get all projects") @@ -51,7 +51,7 @@ def test_get_project_with_empty_name_and_id_raises_value_error(self) -> None: except ValueError as e: assert str(e) == "Exactly one of 'id' or 'name' must be provided." - @patch("galileo.projects.get_project_projects_project_id_get.sync_detailed") + @patch("splunk_ao.projects.get_project_projects_project_id_get.sync_detailed") def test_get_project_with_id_gets_project_by_id(self, get_project_projects_project_id_get: Mock) -> None: # Mock a successful response with parsed project data mock_response = Mock() @@ -63,7 +63,7 @@ def test_get_project_with_id_gets_project_by_id(self, get_project_projects_proje get_project_projects_project_id_get.assert_called_once_with(project_id="123", client=ANY) assert result is None - @patch("galileo.projects.get_project_projects_project_id_get.sync_detailed") + @patch("splunk_ao.projects.get_project_projects_project_id_get.sync_detailed") def test_get_project_with_id_with_whitespace_env_vars_gets_project_by_id( self, get_project_projects_project_id_get: Mock ) -> None: @@ -78,7 +78,7 @@ def test_get_project_with_id_with_whitespace_env_vars_gets_project_by_id( get_project_projects_project_id_get.assert_called_once_with(project_id="123", client=ANY) assert result is None - @patch("galileo.projects.get_project_projects_project_id_get.sync_detailed") + @patch("splunk_ao.projects.get_project_projects_project_id_get.sync_detailed") def test_get_project_with_id_from_env_var_gets_project_by_id( self, get_project_projects_project_id_get: Mock ) -> None: @@ -92,7 +92,7 @@ def test_get_project_with_id_from_env_var_gets_project_by_id( get_project_projects_project_id_get.assert_called_once_with(project_id="123", client=ANY) assert result is None - @patch("galileo.projects.get_projects_projects_get.sync_detailed") + @patch("splunk_ao.projects.get_projects_projects_get.sync_detailed") def test_get_project_with_name_gets_project_by_name(self, get_projects_projects_get: Mock) -> None: mock_response = Mock() mock_response.status_code = httpx.codes.OK @@ -103,7 +103,7 @@ def test_get_project_with_name_gets_project_by_name(self, get_projects_projects_ get_projects_projects_get.assert_called_once_with(project_name="my_project", client=ANY, type_=ANY) assert result is None - @patch("galileo.projects.get_projects_projects_get.sync_detailed") + @patch("splunk_ao.projects.get_projects_projects_get.sync_detailed") def test_get_project_with_name_with_whitespace_env_vars_gets_project_by_name( self, get_projects_projects_get: Mock ) -> None: @@ -118,7 +118,7 @@ def test_get_project_with_name_with_whitespace_env_vars_gets_project_by_name( get_projects_projects_get.assert_called_once_with(project_name="my_project", client=ANY, type_=ANY) assert result is None - @patch("galileo.projects.get_projects_projects_get.sync_detailed") + @patch("splunk_ao.projects.get_projects_projects_get.sync_detailed") def test_get_project_with_name_from_env_var_gets_project_by_name(self, get_projects_projects_get: Mock) -> None: os.environ.pop("SPLUNK_AO_PROJECT_ID", None) mock_response = Mock() @@ -131,14 +131,14 @@ def test_get_project_with_name_from_env_var_gets_project_by_name(self, get_proje get_projects_projects_get.assert_called_once_with(project_name="my_project", client=ANY, type_=ANY) assert result is None - @patch("galileo.projects.create_user_project_collaborators_projects_project_id_users_post.sync") + @patch("splunk_ao.projects.create_user_project_collaborators_projects_project_id_users_post.sync") def test_share_project_with_user(self, mock_create_user_project_collaborators): mock_create_user_project_collaborators.return_value = [Mock()] projects_client = Projects() projects_client.share_project_with_user(project_id="123", user_id="456") mock_create_user_project_collaborators.assert_called_once_with(project_id="123", client=ANY, body=ANY) - @patch("galileo.projects.create_user_project_collaborators_projects_project_id_users_post.sync") + @patch("splunk_ao.projects.create_user_project_collaborators_projects_project_id_users_post.sync") def test_share_project_with_user_error(self, mock_create_user_project_collaborators): """Test that share_project_with_user raises ValueError when the API call returns None.""" mock_create_user_project_collaborators.return_value = None @@ -149,14 +149,14 @@ def test_share_project_with_user_error(self, mock_create_user_project_collaborat assert "Failed to share project 123 with user 456" in str(exc_info.value) - @patch("galileo.projects.delete_user_project_collaborator_projects_project_id_users_user_id_delete.sync") + @patch("splunk_ao.projects.delete_user_project_collaborator_projects_project_id_users_user_id_delete.sync") def test_unshare_project_with_user(self, mock_delete_user_project_collaborator): mock_delete_user_project_collaborator.return_value = True projects_client = Projects() projects_client.unshare_project_with_user(project_id="123", user_id="456") mock_delete_user_project_collaborator.assert_called_once_with(project_id="123", user_id="456", client=ANY) - @patch("galileo.projects.delete_user_project_collaborator_projects_project_id_users_user_id_delete.sync") + @patch("splunk_ao.projects.delete_user_project_collaborator_projects_project_id_users_user_id_delete.sync") def test_unshare_project_with_user_error(self, mock_delete_user_project_collaborator): """Test that unshare_project_with_user raises ValueError when the API call returns None.""" mock_delete_user_project_collaborator.return_value = None @@ -167,7 +167,7 @@ def test_unshare_project_with_user_error(self, mock_delete_user_project_collabor assert "Failed to unshare project 123 with user 456" in str(exc_info.value) - @patch("galileo.projects.list_user_project_collaborators_projects_project_id_users_get.sync") + @patch("splunk_ao.projects.list_user_project_collaborators_projects_project_id_users_get.sync") def test_list_user_project_collaborators(self, mock_list_user_project_collaborators): mock_list_user_project_collaborators.side_effect = [ Mock(collaborators=[Mock()], paginated=True, next_starting_token=1), @@ -178,7 +178,7 @@ def test_list_user_project_collaborators(self, mock_list_user_project_collaborat assert len(collaborators) == 2 assert mock_list_user_project_collaborators.call_count == 2 - @patch("galileo.projects.list_user_project_collaborators_projects_project_id_users_get.sync") + @patch("splunk_ao.projects.list_user_project_collaborators_projects_project_id_users_get.sync") def test_list_user_project_collaborators_error(self, mock_list_user_project_collaborators): """Test that list_user_project_collaborators raises ValueError when the API call returns None.""" mock_list_user_project_collaborators.return_value = None @@ -189,7 +189,7 @@ def test_list_user_project_collaborators_error(self, mock_list_user_project_coll assert "Failed to list collaborators for project 123" in str(exc_info.value) - @patch("galileo.projects.update_user_project_collaborator_projects_project_id_users_user_id_patch.sync") + @patch("splunk_ao.projects.update_user_project_collaborator_projects_project_id_users_user_id_patch.sync") def test_update_user_project_collaborator(self, mock_update_user_project_collaborator): projects_client = Projects() projects_client.update_user_project_collaborator(project_id="123", user_id="456") @@ -197,7 +197,7 @@ def test_update_user_project_collaborator(self, mock_update_user_project_collabo project_id="123", user_id="456", client=ANY, body=ANY ) - @patch("galileo.projects.update_user_project_collaborator_projects_project_id_users_user_id_patch.sync") + @patch("splunk_ao.projects.update_user_project_collaborator_projects_project_id_users_user_id_patch.sync") def test_update_user_project_collaborator_error(self, mock_update_user_project_collaborator): """Test that update_user_project_collaborator raises ValueError when the API call returns None.""" mock_update_user_project_collaborator.return_value = None @@ -230,8 +230,8 @@ def test_delete_project_with_empty_name_and_id_raises_value_error(self) -> None: assert "Exactly one of 'id' or 'name' must be provided." in str(exc_info.value) - @patch("galileo.projects.delete_project_projects_project_id_delete.sync_detailed") - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.delete_project_projects_project_id_delete.sync_detailed") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_with_id_deletes_project_by_id(self, get_mock: Mock, delete_project_mock: Mock) -> None: # Mock the get method to return a project with the expected ID mock_project = Mock() @@ -251,8 +251,8 @@ def test_delete_project_with_id_deletes_project_by_id(self, get_mock: Mock, dele delete_project_mock.assert_called_once_with(project_id="123", client=ANY) assert result is True - @patch("galileo.projects.delete_project_projects_project_id_delete.sync_detailed") - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.delete_project_projects_project_id_delete.sync_detailed") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_with_name_deletes_project_by_name(self, get_mock: Mock, delete_project_mock: Mock) -> None: # Mock the get method to return a project with the expected ID mock_project = Mock() @@ -272,7 +272,7 @@ def test_delete_project_with_name_deletes_project_by_name(self, get_mock: Mock, delete_project_mock.assert_called_once_with(project_id="456", client=ANY) assert result is True - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_with_non_genai_project_raises_api_exception(self, get_mock: Mock) -> None: """Test that delete_project raises ProjectsAPIException when project is not GEN_AI type.""" # Mock the get method to return a non-GEN_AI project @@ -288,7 +288,7 @@ def test_delete_project_with_non_genai_project_raises_api_exception(self, get_mo assert "is not a gen_ai project" in str(exc_info.value) - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_with_nonexistent_project_raises_value_error(self, get_mock: Mock) -> None: """Test that delete_project raises ValueError when project doesn't exist.""" # Mock the get method to return None (project not found) @@ -317,7 +317,7 @@ def test_delete_project_convenience_with_both_name_and_id_raises_value_error(sel assert "Exactly one of 'id' or 'name' must be provided." in str(exc_info.value) - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_convenience_with_nonexistent_project_raises_value_error(self, get_mock: Mock) -> None: """Test that delete_project convenience function raises ValueError when project doesn't exist.""" # Mock the get method to return None (project not found) @@ -328,8 +328,8 @@ def test_delete_project_convenience_with_nonexistent_project_raises_value_error( assert "not found" in str(exc_info.value) - @patch("galileo.projects.delete_project_projects_project_id_delete.sync_detailed") - @patch("galileo.projects.Projects.get") + @patch("splunk_ao.projects.delete_project_projects_project_id_delete.sync_detailed") + @patch("splunk_ao.projects.Projects.get") def test_delete_project_convenience_successful_deletion_returns_true( self, get_mock: Mock, delete_project_mock: Mock ) -> None: diff --git a/tests/test_prompt.py b/tests/test_prompt.py index a2a18fad..552e665e 100644 --- a/tests/test_prompt.py +++ b/tests/test_prompt.py @@ -3,12 +3,12 @@ import pytest -from galileo.prompt import Prompt, PromptVersion, _parse_template_to_messages from galileo.resources.models.messages_list_item import MessagesListItem -from galileo.schema.message import Message -from galileo.shared.base import SyncState -from galileo.shared.exceptions import ResourceNotFoundError, ValidationError from galileo_core.schemas.logging.llm import MessageRole +from splunk_ao.prompt import Prompt, PromptVersion, _parse_template_to_messages +from splunk_ao.schema.message import Message +from splunk_ao.shared.base import SyncState +from splunk_ao.shared.exceptions import ResourceNotFoundError, ValidationError class TestPromptInitialization: @@ -68,8 +68,8 @@ def test_init_without_required_fields_raises_error( class TestPromptCreate: """Test suite for Prompt.create() method.""" - @patch("galileo.prompt.Projects") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.Projects") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_persists_prompt_to_api( self, mock_templates_class: MagicMock, @@ -100,8 +100,8 @@ def test_create_persists_prompt_to_api( assert prompt.selected_version_number == 1 assert prompt.total_versions == 1 - @patch("galileo.prompt.Projects") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.Projects") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_with_project_association( self, mock_templates_class: MagicMock, @@ -134,8 +134,8 @@ def test_create_with_project_association( assert prompt.project_id == mock_project.id assert prompt.project_name == mock_project.name - @patch("galileo.prompt.Projects") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.Projects") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_handles_api_failure( self, mock_templates_class: MagicMock, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -158,8 +158,8 @@ def test_create_handles_api_failure( assert prompt.sync_state == SyncState.FAILED_SYNC - @patch("galileo.prompt.Projects") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.Projects") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_raises_resource_not_found_when_explicit_project_cannot_be_resolved( self, mock_templates_class: MagicMock, mock_projects_class: MagicMock, reset_configuration: None ) -> None: @@ -186,7 +186,7 @@ class TestPromptGet: """Test suite for Prompt.get() class method.""" @pytest.mark.parametrize("lookup_key", ["name", "id"]) - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_get_returns_prompt( self, mock_templates_class: MagicMock, lookup_key: str, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -201,7 +201,7 @@ def test_get_returns_prompt( assert prompt is not None assert prompt.is_synced() - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_get_returns_none_when_not_found(self, mock_templates_class: MagicMock, reset_configuration: None) -> None: """Test get() returns None when prompt is not found.""" mock_service = MagicMock() @@ -228,7 +228,7 @@ def test_get_validates_parameters(self, kwargs: dict, expected_error: str, reset class TestPromptList: """Test suite for Prompt.list() class method.""" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_list_returns_all_prompts(self, mock_templates_class: MagicMock, reset_configuration: None) -> None: """Test list() returns a list of synced prompt instances.""" mock_service = MagicMock() @@ -260,7 +260,7 @@ def test_list_returns_all_prompts(self, mock_templates_class: MagicMock, reset_c class TestPromptUpdate: """Test suite for Prompt.update() method.""" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_update_name( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -304,7 +304,7 @@ def test_update_raises_error_for_local_only(self, reset_configuration: None) -> class TestPromptDelete: """Test suite for Prompt.delete() method.""" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_delete_removes_prompt( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -331,7 +331,7 @@ def test_delete_raises_error_for_local_only(self, reset_configuration: None) -> class TestPromptRefresh: """Test suite for Prompt.refresh() method.""" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_refresh_updates_attributes(self, mock_templates_class: MagicMock, reset_configuration: None) -> None: """Test refresh() updates all attributes from the API.""" mock_service = MagicMock() @@ -385,10 +385,10 @@ def test_refresh_raises_error_for_local_only(self, reset_configuration: None) -> class TestPromptMethods: """Test suite for other Prompt methods.""" - @patch("galileo.prompt.SplunkAOConfig") - @patch("galileo.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") - @patch("galileo.prompt.create_global_prompt_template_version_templates_template_id_versions_post") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.SplunkAOConfig") + @patch("splunk_ao.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") + @patch("splunk_ao.prompt.create_global_prompt_template_version_templates_template_id_versions_post") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_version_creates_actual_version( self, mock_templates_class: MagicMock, @@ -441,10 +441,10 @@ def test_create_version_creates_actual_version( assert prompt.is_synced() assert prompt.selected_version_number == 2 - @patch("galileo.prompt.SplunkAOConfig") - @patch("galileo.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") - @patch("galileo.prompt.create_global_prompt_template_version_templates_template_id_versions_post") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.SplunkAOConfig") + @patch("splunk_ao.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") + @patch("splunk_ao.prompt.create_global_prompt_template_version_templates_template_id_versions_post") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_create_version_with_new_messages( self, mock_templates_class: MagicMock, @@ -508,8 +508,8 @@ def test_create_version_raises_error_for_local_only(self, reset_configuration: N with pytest.raises(ValueError, match="Prompt ID is not set"): prompt.create_version() - @patch("galileo.prompt.Projects") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.Projects") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_creates_prompt_when_local_only( self, mock_templates_class: MagicMock, @@ -538,7 +538,7 @@ def test_save_creates_prompt_when_local_only( assert result is prompt assert prompt.is_synced() - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_returns_self_when_already_synced( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -598,7 +598,7 @@ def test_repr_includes_version_when_available(self, reset_configuration: None) - class TestPromptSave: """Test suite for Prompt.save() — focused on the DIRTY branch and dirty tracking.""" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_dirty_calls_update_and_syncs_attributes( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -627,7 +627,7 @@ def test_save_dirty_calls_update_and_syncs_attributes( assert result.updated_at == updated_response.updated_at assert result.is_synced() - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_without_id_raises_value_error( self, mock_templates_class: MagicMock, reset_configuration: None ) -> None: @@ -640,7 +640,7 @@ def test_save_without_id_raises_value_error( with pytest.raises(ValueError, match="Prompt ID is not set"): prompt.save() - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_handles_api_failure( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -661,7 +661,7 @@ def test_save_handles_api_failure( assert prompt.sync_state == SyncState.FAILED_SYNC - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_name_assignment_transitions_synced_to_dirty( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -687,7 +687,7 @@ def test_name_assignment_during_init_stays_local_only(self, reset_configuration: # Then: state is LOCAL_ONLY, not DIRTY assert prompt.sync_state == SyncState.LOCAL_ONLY - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_same_value_assignment_stays_synced( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -706,7 +706,7 @@ def test_same_value_assignment_stays_synced( # Then: state stays SYNCED (no redundant API call on save) assert prompt.sync_state == SyncState.SYNCED - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_save_failed_sync_raises_value_error( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -722,7 +722,7 @@ def test_save_failed_sync_raises_value_error( with pytest.raises(ValueError, match="FAILED_SYNC"): prompt.save() - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_refresh_does_not_trigger_dirty( self, mock_templates_class: MagicMock, reset_configuration: None, mock_prompt: MagicMock ) -> None: @@ -805,7 +805,7 @@ def test_parse_template_with_invalid_json(self) -> None: assert messages[0].role == MessageRole.user assert messages[0].content == "{not valid json}" - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_get_parses_json_string_template_correctly( self, mock_templates_class: MagicMock, reset_configuration: None ) -> None: @@ -847,9 +847,9 @@ def test_get_parses_json_string_template_correctly( class TestVersionManagement: """Test suite for version management methods.""" - @patch("galileo.prompt.SplunkAOConfig") - @patch("galileo.prompt.query_template_versions_templates_template_id_versions_query_post") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.SplunkAOConfig") + @patch("splunk_ao.prompt.query_template_versions_templates_template_id_versions_query_post") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_list_versions_returns_version_objects( self, mock_templates_class: MagicMock, @@ -901,9 +901,9 @@ def test_list_versions_raises_error_for_local_only(self, reset_configuration: No with pytest.raises(ValueError, match="Prompt ID is not set"): prompt.list_versions() - @patch("galileo.prompt.SplunkAOConfig") - @patch("galileo.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") - @patch("galileo.prompt.GlobalPromptTemplates") + @patch("splunk_ao.prompt.SplunkAOConfig") + @patch("splunk_ao.prompt.set_selected_global_template_version_templates_template_id_versions_version_put") + @patch("splunk_ao.prompt.GlobalPromptTemplates") def test_select_version_sets_active_version( self, mock_templates_class: MagicMock, diff --git a/tests/test_prompts.py b/tests/test_prompts.py index 815c095d..fc353471 100644 --- a/tests/test_prompts.py +++ b/tests/test_prompts.py @@ -4,16 +4,6 @@ import pytest -from galileo import Message, MessageRole -from galileo.prompts import ( - PromptTemplateAPIException, - create_prompt, - delete_prompt, - get_prompt, - get_prompts, - render_template, - update_prompt, -) from galileo.resources.models import ( BasePromptTemplateResponse, BasePromptTemplateVersionResponse, @@ -32,6 +22,16 @@ UpdatePromptTemplateRequest, ) from galileo.resources.types import Response +from splunk_ao import Message, MessageRole +from splunk_ao.prompts import ( + PromptTemplateAPIException, + create_prompt, + delete_prompt, + get_prompt, + get_prompts, + render_template, + update_prompt, +) def projects_response(): @@ -386,8 +386,8 @@ def render_template_response_second_page(): ) -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_global_prompt_template(create_global_prompt_template_mock: Mock, query_templates_mock: Mock) -> None: # Mock no existing templates (name is unique) query_templates_mock.sync.return_value = empty_templates_list_response() @@ -414,8 +414,8 @@ def test_create_global_prompt_template(create_global_prompt_template_mock: Mock, ) -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_global_prompt_template_error_scenarios( create_global_prompt_template_mock: Mock, query_templates_mock: Mock ) -> None: @@ -450,7 +450,7 @@ def test_create_global_prompt_template_error_scenarios( assert create_global_prompt_template_mock.sync_detailed.call_count == 2 -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_get_global_prompt_template_by_id(get_global_template_mock: Mock) -> None: get_global_template_mock.sync.return_value = global_prompt_template() @@ -465,7 +465,7 @@ def test_get_global_prompt_template_by_id(get_global_template_mock: Mock) -> Non get_global_template_mock.sync.assert_called_once_with(template_id="global-template-id-123", client=ANY) -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_get_global_prompt_template_by_name(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = global_templates_list_response() @@ -480,7 +480,7 @@ def test_get_global_prompt_template_by_name(query_templates_mock: Mock) -> None: query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_get_global_prompt_template_by_id_not_found(get_global_template_mock: Mock) -> None: get_global_template_mock.sync.return_value = None @@ -490,7 +490,7 @@ def test_get_global_prompt_template_by_id_not_found(get_global_template_mock: Mo get_global_template_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_get_global_prompt_template_by_name_not_found(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = empty_templates_list_response() @@ -510,7 +510,7 @@ def test_get_global_prompt_template_validation_errors() -> None: assert str(exc_info.value) == "Exactly one of 'id' or 'name' must be provided" -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_list_global_prompt_templates(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = global_templates_list_response() @@ -522,7 +522,7 @@ def test_list_global_prompt_templates(query_templates_mock: Mock) -> None: query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_list_global_prompt_templates_with_filter(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = global_templates_list_response() @@ -542,7 +542,7 @@ def test_list_global_prompt_templates_with_filter(query_templates_mock: Mock) -> ) -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") @pytest.mark.parametrize("response_value", [HTTPValidationError(), None]) def test_list_global_prompt_templates_with_error_responses(query_templates_mock: Mock, response_value) -> None: """Test list_global_prompt_templates when API returns HTTPValidationError or None.""" @@ -554,7 +554,7 @@ def test_list_global_prompt_templates_with_error_responses(query_templates_mock: query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_list_global_prompt_templates_empty(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = empty_templates_list_response() @@ -564,7 +564,7 @@ def test_list_global_prompt_templates_empty(query_templates_mock: Mock) -> None: query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") def test_delete_global_prompt_template_by_id(delete_global_template_mock: Mock) -> None: delete_global_template_mock.sync.return_value = None @@ -573,8 +573,8 @@ def test_delete_global_prompt_template_by_id(delete_global_template_mock: Mock) delete_global_template_mock.sync.assert_called_once_with(client=ANY, template_id="global-template-id-123") -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") def test_delete_global_prompt_template_by_name(delete_global_template_mock: Mock, query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = global_templates_list_response() delete_global_template_mock.sync.return_value = None @@ -585,7 +585,7 @@ def test_delete_global_prompt_template_by_name(delete_global_template_mock: Mock delete_global_template_mock.sync.assert_called_once_with(client=ANY, template_id="global-template-id-123") -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_delete_global_prompt_template_by_name_not_found(query_templates_mock: Mock) -> None: query_templates_mock.sync.return_value = empty_templates_list_response() @@ -611,7 +611,7 @@ def test_delete_global_prompt_template_validation_errors() -> None: assert str(exc_info.value) == "Exactly one of 'id' or 'name' must be provided" -@patch("galileo.prompts.update_global_template_templates_template_id_patch") +@patch("splunk_ao.prompts.update_global_template_templates_template_id_patch") def test_update_global_prompt_template_by_id(update_global_template_mock: Mock) -> None: """Test update_prompt with template ID.""" updated_template = global_prompt_template() @@ -631,8 +631,8 @@ def test_update_global_prompt_template_by_id(update_global_template_mock: Mock) ) -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.update_global_template_templates_template_id_patch") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.update_global_template_templates_template_id_patch") def test_update_global_prompt_template_by_name(update_global_template_mock: Mock, query_templates_mock: Mock) -> None: """Test update_prompt with template name.""" query_templates_mock.sync.return_value = global_templates_list_response() @@ -656,7 +656,7 @@ def test_update_global_prompt_template_by_name(update_global_template_mock: Mock ) -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_update_global_prompt_template_by_name_not_found(query_templates_mock: Mock) -> None: """Test update_prompt when template is not found by name.""" query_templates_mock.sync.return_value = empty_templates_list_response() @@ -668,7 +668,7 @@ def test_update_global_prompt_template_by_name_not_found(query_templates_mock: M query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.update_global_template_templates_template_id_patch") +@patch("splunk_ao.prompts.update_global_template_templates_template_id_patch") def test_update_global_prompt_template_error_scenarios(update_global_template_mock: Mock) -> None: """Test update_prompt with realistic error scenarios.""" @@ -727,7 +727,7 @@ def test_update_global_prompt_template_validation_errors() -> None: assert str(exc_info.value) == "Exactly one of 'id' or 'name' must be provided" -@patch("galileo.prompts.update_global_template_templates_template_id_patch") +@patch("splunk_ao.prompts.update_global_template_templates_template_id_patch") def test_update_global_prompt_template_with_empty_name(update_global_template_mock: Mock) -> None: """Test update_prompt with empty name (should be handled by API validation).""" update_global_template_mock.sync_detailed.return_value = Response( @@ -746,7 +746,7 @@ def test_update_global_prompt_template_with_empty_name(update_global_template_mo ) -@patch("galileo.prompts.update_global_template_templates_template_id_patch") +@patch("splunk_ao.prompts.update_global_template_templates_template_id_patch") def test_update_global_prompt_template_successful_response_with_http_validation_error( update_global_template_mock: Mock, ) -> None: @@ -765,7 +765,7 @@ def test_update_global_prompt_template_successful_response_with_http_validation_ update_global_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_with_string_data(render_template_mock: Mock) -> None: """Test render_template with string data.""" render_template_mock.sync_detailed.return_value = Response( @@ -788,7 +788,7 @@ def test_render_template_with_string_data(render_template_mock: Mock) -> None: ) -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_with_dataset_data(render_template_mock: Mock) -> None: """Test render_template with dataset data.""" render_template_mock.sync_detailed.return_value = Response( @@ -809,7 +809,7 @@ def test_render_template_with_dataset_data(render_template_mock: Mock) -> None: ) -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_with_pagination(render_template_mock: Mock) -> None: """Test render_template with pagination parameters for both page 1 and page 2.""" # Test page 1 (starting_token=0, limit=1) @@ -863,7 +863,7 @@ def test_render_template_with_pagination(render_template_mock: Mock) -> None: ) -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_with_dataset_data_object(render_template_mock: Mock) -> None: """Test render_template with DatasetData object.""" render_template_mock.sync_detailed.return_value = Response( @@ -882,7 +882,7 @@ def test_render_template_with_dataset_data_object(render_template_mock: Mock) -> ) -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_with_string_data_object(render_template_mock: Mock) -> None: """Test render_template with StringData object.""" render_template_mock.sync_detailed.return_value = Response( @@ -901,7 +901,7 @@ def test_render_template_with_string_data_object(render_template_mock: Mock) -> ) -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_empty_response(render_template_mock: Mock) -> None: """Test render_template with empty response.""" render_template_mock.sync_detailed.return_value = Response( @@ -915,7 +915,7 @@ def test_render_template_empty_response(render_template_mock: Mock) -> None: render_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.render_template_render_template_post") +@patch("splunk_ao.prompts.render_template_render_template_post") def test_render_template_none_response(render_template_mock: Mock) -> None: """Test render_template when API returns None.""" render_template_mock.sync_detailed.return_value = Response( @@ -928,9 +928,9 @@ def test_render_template_none_response(render_template_mock: Mock) -> None: render_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_projects_projects_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_projects_projects_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_with_project_name( create_prompt_template_mock: Mock, get_projects_projects_get_mock: Mock, query_templates_mock: Mock ) -> None: @@ -955,8 +955,8 @@ def test_create_prompt_with_project_name( get_projects_projects_get_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_with_project_id(create_prompt_template_mock: Mock, query_templates_mock: Mock) -> None: """Test create_prompt with project_id parameter.""" # Mock no existing templates (name is unique) @@ -980,9 +980,9 @@ def test_create_prompt_with_project_id(create_prompt_template_mock: Mock, query_ assert call_kwargs.kwargs["project_id"] == "e343ea54-4df3-4d0b-9bc5-7e8224be348f" -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.projects.get_projects_projects_get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.projects.get_projects_projects_get") def test_create_prompt_with_nonexistent_project_name( get_projects_projects_get_mock: Mock, get_all_projects_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1008,8 +1008,8 @@ def test_create_prompt_with_nonexistent_project_name( get_projects_projects_get_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_with_nonexistent_project_id( create_prompt_template_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1050,9 +1050,9 @@ def test_create_prompt_with_both_project_params() -> None: assert "Only one of 'project_id' or 'project_name' can be provided" in str(exc_info.value) -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_without_project_creates_global( create_global_prompt_template_mock: Mock, get_all_projects_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1076,10 +1076,10 @@ def test_create_prompt_without_project_creates_global( create_global_prompt_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.projects.get_projects_projects_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.projects.get_projects_projects_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_with_project_name_and_string_template( create_prompt_template_mock: Mock, get_projects_projects_get_mock: Mock, @@ -1110,7 +1110,7 @@ def test_create_prompt_with_project_name_and_string_template( # Test get_prompt() with project parameters (for backward compatibility) -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_get_prompt_with_project_name_and_id(get_template_mock: Mock) -> None: """Test get_prompt with project_name parameter - should work (params ignored).""" get_template_mock.sync.return_value = prompt_template() @@ -1122,7 +1122,7 @@ def test_get_prompt_with_project_name_and_id(get_template_mock: Mock) -> None: get_template_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_get_prompt_with_project_name_and_name(query_templates_mock: Mock) -> None: """Test get_prompt with project_name parameter by name - should work (params ignored).""" query_templates_mock.sync.return_value = ListPromptTemplateResponse( @@ -1136,7 +1136,7 @@ def test_get_prompt_with_project_name_and_name(query_templates_mock: Mock) -> No query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_get_prompt_with_deprecated_project_id(get_template_mock: Mock) -> None: """Test get_prompt with project_id parameter - should work (params ignored).""" get_template_mock.sync.return_value = prompt_template() @@ -1155,7 +1155,7 @@ def test_get_prompt_project_params_are_ignored() -> None: # Test delete_prompt() with project parameters (for backward compatibility) -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") def test_delete_prompt_with_project_name_and_id(delete_template_mock: Mock) -> None: """Test delete_prompt with project_name parameter - should work (params ignored).""" delete_template_mock.sync.return_value = None @@ -1165,8 +1165,8 @@ def test_delete_prompt_with_project_name_and_id(delete_template_mock: Mock) -> N delete_template_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") def test_delete_prompt_with_project_name_and_name(delete_template_mock: Mock, query_templates_mock: Mock) -> None: """Test delete_prompt with project_name parameter by name - should work (params ignored).""" delete_template_mock.sync.return_value = None @@ -1179,7 +1179,7 @@ def test_delete_prompt_with_project_name_and_name(delete_template_mock: Mock, qu delete_template_mock.sync.assert_called_once() -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") def test_delete_prompt_with_project_id(delete_template_mock: Mock) -> None: """Test delete_prompt with project_id parameter - should work (params ignored).""" delete_template_mock.sync.return_value = None @@ -1189,7 +1189,7 @@ def test_delete_prompt_with_project_id(delete_template_mock: Mock) -> None: delete_template_mock.sync.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_delete_prompt_with_project_name_template_not_found(query_templates_mock: Mock) -> None: """Test delete_prompt with project_name when template is not found.""" query_templates_mock.sync.return_value = ListPromptTemplateResponse(templates=[], next_starting_token=None) @@ -1207,9 +1207,9 @@ def test_delete_prompt_project_params_are_ignored() -> None: # Test organization-wide unique name generation -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_generates_unique_name_when_global_exists( create_global_prompt_template_mock: Mock, get_all_projects_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1245,8 +1245,8 @@ def test_create_prompt_generates_unique_name_when_global_exists( assert " (1)" in call_kwargs.kwargs["body"].name or call_kwargs.kwargs["body"].name == "global-helpful-assistant" -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_generates_unique_name_when_project_exists( create_global_prompt_template_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1281,10 +1281,10 @@ def test_create_prompt_generates_unique_name_when_project_exists( assert template.name == "my-template (1)" # Should have (1) appended -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.projects.get_projects_projects_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.projects.get_projects_projects_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_with_project_generates_unique_name( create_prompt_template_mock: Mock, get_projects_projects_get_mock: Mock, @@ -1331,9 +1331,9 @@ def test_create_prompt_with_project_generates_unique_name( create_prompt_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.get_all_projects_projects_all_get") -@patch("galileo.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.get_all_projects_projects_all_get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") def test_create_prompt_no_increment_when_name_unique( create_global_prompt_template_mock: Mock, get_all_projects_mock: Mock, query_templates_mock: Mock ) -> None: @@ -1364,10 +1364,10 @@ def test_create_prompt_no_increment_when_name_unique( assert call_kwargs.kwargs["body"].name == "unique-template" -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_generate_unique_name_increments_multiple_times(query_templates_mock: Mock) -> None: """Test that unique name generation can handle multiple increments.""" - from galileo.utils.prompts import generate_unique_name + from splunk_ao.utils.prompts import generate_unique_name # Mock global templates: base-name, base-name (1), and base-name (2) all exist template1 = global_prompt_template() @@ -1399,11 +1399,11 @@ def test_generate_unique_name_increments_multiple_times(query_templates_mock: Mo # ================================ -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.Projects.get") def test_list_prompt_templates_deprecated(mock_projects_get: Mock, query_templates_mock: Mock) -> None: """Test that list_prompt_templates() still works but emits deprecation warning.""" - from galileo.prompts import list_prompt_templates + from splunk_ao.prompts import list_prompt_templates # Mock the project mock_project = Mock() @@ -1431,11 +1431,11 @@ def test_list_prompt_templates_deprecated(mock_projects_get: Mock, query_templat query_templates_mock.sync.assert_called_once() -@patch("galileo.prompts.get_global_template_templates_template_id_get") -@patch("galileo.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") def test_get_prompt_template_deprecated(query_templates_mock: Mock, get_template_mock: Mock) -> None: """Test that get_prompt_template() still works but emits deprecation warning.""" - from galileo.prompts import get_prompt_template + from splunk_ao.prompts import get_prompt_template # Mock the response template = global_prompt_template() @@ -1462,11 +1462,11 @@ def test_get_prompt_template_deprecated(query_templates_mock: Mock, get_template assert result.name == "my-template" -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.Projects.get") def test_prompt_templates_class_deprecated(mock_projects_get: Mock, query_templates_mock: Mock) -> None: """Test that PromptTemplates class still works but emits deprecation warning.""" - from galileo.prompts import PromptTemplates + from splunk_ao.prompts import PromptTemplates # Mock the project mock_project = Mock() @@ -1494,7 +1494,7 @@ def test_prompt_templates_class_deprecated(mock_projects_get: Mock, query_templa assert templates_list[0].name == template.name -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_get_prompt_with_project_params_deprecated(get_template_mock: Mock) -> None: """Test that get_prompt() with project params emits deprecation warning.""" # Mock the response @@ -1517,8 +1517,8 @@ def test_get_prompt_with_project_params_deprecated(get_template_mock: Mock) -> N assert result.name == "my-template" -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") -@patch("galileo.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") def test_delete_prompt_with_project_params_deprecated(get_template_mock: Mock, delete_template_mock: Mock) -> None: """Test that delete_prompt() with project params emits deprecation warning.""" # Mock the response @@ -1540,14 +1540,14 @@ def test_delete_prompt_with_project_params_deprecated(get_template_mock: Mock, d delete_template_mock.sync.assert_called_once() -@patch("galileo.prompts.create_global_prompt_template_templates_post") -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.Projects.get") def test_create_prompt_template_still_works( mock_projects_get: Mock, query_templates_mock: Mock, create_global_prompt_template_mock: Mock ) -> None: """Test that the old create_prompt_template() function still works but emits deprecation warning.""" - from galileo.prompts import create_prompt_template + from splunk_ao.prompts import create_prompt_template # Mock the project mock_project = Mock() @@ -1577,12 +1577,12 @@ def test_create_prompt_template_still_works( create_global_prompt_template_mock.sync_detailed.assert_called_once() -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.prompts.create_global_prompt_template_templates_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.prompts.create_global_prompt_template_templates_post") +@patch("splunk_ao.projects.Projects.get") def test_prompt_templates_create_method(mock_projects_get: Mock, create_mock: Mock, query_templates_mock: Mock) -> None: """Test that PromptTemplates.create() method works.""" - from galileo.prompts import PromptTemplates + from splunk_ao.prompts import PromptTemplates # Mock the project mock_project = Mock() @@ -1612,12 +1612,12 @@ def test_prompt_templates_create_method(mock_projects_get: Mock, create_mock: Mo assert template.name == "test-template" -@patch("galileo.prompts.get_global_template_templates_template_id_get") -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.Projects.get") def test_prompt_templates_get_method(mock_projects_get: Mock, query_templates_mock: Mock, get_mock: Mock) -> None: """Test that PromptTemplates.get() method works.""" - from galileo.prompts import PromptTemplates + from splunk_ao.prompts import PromptTemplates # Mock the project mock_project = Mock() @@ -1650,15 +1650,15 @@ def test_prompt_templates_get_method(mock_projects_get: Mock, query_templates_mo assert result.name == "my-template" -@patch("galileo.prompts.delete_global_template_templates_template_id_delete") -@patch("galileo.prompts.get_global_template_templates_template_id_get") -@patch("galileo.prompts.query_templates_templates_query_post") -@patch("galileo.projects.Projects.get") +@patch("splunk_ao.prompts.delete_global_template_templates_template_id_delete") +@patch("splunk_ao.prompts.get_global_template_templates_template_id_get") +@patch("splunk_ao.prompts.query_templates_templates_query_post") +@patch("splunk_ao.projects.Projects.get") def test_prompt_templates_delete_method( mock_projects_get: Mock, query_templates_mock: Mock, get_mock: Mock, delete_mock: Mock ) -> None: """Test that PromptTemplates.delete() method works.""" - from galileo.prompts import PromptTemplates + from splunk_ao.prompts import PromptTemplates # Mock the project mock_project = Mock() diff --git a/tests/test_prompts_global.py b/tests/test_prompts_global.py index 3ca5716f..ad2f3e94 100644 --- a/tests/test_prompts_global.py +++ b/tests/test_prompts_global.py @@ -8,8 +8,8 @@ import pytest from respx import MockRouter -from galileo import Message, MessageRole -from galileo.prompts import create_prompt, delete_prompt, get_prompt, get_prompts +from splunk_ao import Message, MessageRole +from splunk_ao.prompts import create_prompt, delete_prompt, get_prompt, get_prompts @pytest.fixture diff --git a/tests/test_protect.py b/tests/test_protect.py index f6f5c565..c6e7e52a 100644 --- a/tests/test_protect.py +++ b/tests/test_protect.py @@ -3,8 +3,6 @@ from pytest import mark -from galileo.handlers.langchain.tool import ProtectTool -from galileo.protect import Protect, ainvoke_protect, invoke_protect from galileo.resources.models.execution_status import ExecutionStatus as APIExecutionStatus from galileo.resources.models.http_validation_error import HTTPValidationError from galileo.resources.models.protect_request import ProtectRequest as APIRequest @@ -16,6 +14,8 @@ from galileo_core.schemas.protect.response import Response from galileo_core.schemas.protect.rule import Rule, RuleOperator from galileo_core.schemas.protect.ruleset import Ruleset +from splunk_ao.handlers.langchain.tool import ProtectTool +from splunk_ao.protect import Protect, ainvoke_protect, invoke_protect A_PROJECT_NAME = "project_name" A_STAGE_NAME = "stage_name" @@ -98,7 +98,7 @@ def invoke_response() -> APIResponse: Payload(input=A_PROTECT_INPUT, output=A_PROTECT_INPUT), ], ) -@patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) +@patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) class TestAInvoke: @mark.asyncio async def test_ainvoke_success( @@ -170,7 +170,7 @@ async def test_ainvoke_success( # --------------------------------------------------------------------------- class TestAInvokePassThrough: @mark.parametrize("timeout", [5, 60]) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_ainvoke_forwards_timeout(self, mock_invoke_post_async: AsyncMock, timeout: float) -> None: mock_invoke_post_async.return_value = invoke_response() @@ -188,7 +188,7 @@ async def test_ainvoke_forwards_timeout(self, mock_invoke_post_async: AsyncMock, assert body.timeout == timeout @mark.parametrize("metadata", [None, {"key": "value"}]) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_ainvoke_forwards_metadata(self, mock_invoke_post_async: AsyncMock, metadata: dict | None) -> None: mock_invoke_post_async.return_value = invoke_response() @@ -209,7 +209,7 @@ async def test_ainvoke_forwards_metadata(self, mock_invoke_post_async: AsyncMock assert body.metadata.additional_properties == metadata @mark.parametrize("headers", [None, {"key": "value"}]) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_ainvoke_forwards_headers(self, mock_invoke_post_async: AsyncMock, headers: dict | None) -> None: mock_invoke_post_async.return_value = invoke_response() @@ -230,7 +230,7 @@ async def test_ainvoke_forwards_headers(self, mock_invoke_post_async: AsyncMock, assert body.headers.additional_properties == headers @mark.parametrize("stage_version", [None, 1, 2]) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_ainvoke_forwards_stage_version( self, mock_invoke_post_async: AsyncMock, stage_version: int | None @@ -278,7 +278,7 @@ async def test_ainvoke_forwards_stage_version( ], ) class TestInvoke: - @patch("galileo.protect.ainvoke_protect") + @patch("splunk_ao.protect.ainvoke_protect") def test_invoke_success( self, mock_ainvoke_protect: Mock, @@ -288,7 +288,7 @@ def test_invoke_success( include_stage_id: bool, payload: Payload, ) -> None: - with patch("galileo.protect.async_run") as mock_async_run: + with patch("splunk_ao.protect.async_run") as mock_async_run: project_id = uuid4() if include_project_id else None project_name = A_PROJECT_NAME if include_project_name else None stage_id = uuid4() if include_stage_id else None @@ -320,7 +320,7 @@ def test_invoke_success( headers=DEFAULT_HEADERS, ) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_langchain_tool( self, @@ -371,36 +371,36 @@ async def test_langchain_tool( # --------------------------------------------------------------------------- class TestInvokePassThrough: @mark.parametrize("timeout", [5, 60]) - @patch("galileo.protect.ainvoke_protect") + @patch("splunk_ao.protect.ainvoke_protect") def test_invoke_forwards_timeout(self, mock_ainvoke_protect: Mock, timeout: float) -> None: - with patch("galileo.protect.async_run"): + with patch("splunk_ao.protect.async_run"): invoke_protect( payload=Payload(input=A_PROTECT_INPUT), stage_id=uuid4(), stage_name=A_STAGE_NAME, timeout=timeout ) assert mock_ainvoke_protect.call_args.kwargs["timeout"] == timeout @mark.parametrize("metadata", [None, {"key": "value"}]) - @patch("galileo.protect.ainvoke_protect") + @patch("splunk_ao.protect.ainvoke_protect") def test_invoke_forwards_metadata(self, mock_ainvoke_protect: Mock, metadata: dict | None) -> None: - with patch("galileo.protect.async_run"): + with patch("splunk_ao.protect.async_run"): invoke_protect( payload=Payload(input=A_PROTECT_INPUT), stage_id=uuid4(), stage_name=A_STAGE_NAME, metadata=metadata ) assert mock_ainvoke_protect.call_args.kwargs["metadata"] == metadata @mark.parametrize("headers", [None, {"key": "value"}]) - @patch("galileo.protect.ainvoke_protect") + @patch("splunk_ao.protect.ainvoke_protect") def test_invoke_forwards_headers(self, mock_ainvoke_protect: Mock, headers: dict | None) -> None: - with patch("galileo.protect.async_run"): + with patch("splunk_ao.protect.async_run"): invoke_protect( payload=Payload(input=A_PROTECT_INPUT), stage_id=uuid4(), stage_name=A_STAGE_NAME, headers=headers ) assert mock_ainvoke_protect.call_args.kwargs["headers"] == headers @mark.parametrize("stage_version", [None, 1, 2]) - @patch("galileo.protect.ainvoke_protect") + @patch("splunk_ao.protect.ainvoke_protect") def test_invoke_forwards_stage_version(self, mock_ainvoke_protect: Mock, stage_version: int | None) -> None: - with patch("galileo.protect.async_run"): + with patch("splunk_ao.protect.async_run"): invoke_protect( payload=Payload(input=A_PROTECT_INPUT), stage_id=uuid4(), @@ -409,7 +409,7 @@ def test_invoke_forwards_stage_version(self, mock_ainvoke_protect: Mock, stage_v ) assert mock_ainvoke_protect.call_args.kwargs["stage_version"] == stage_version - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_langchain_tool_forwards_timeout(self, mock_invoke_post_async: AsyncMock) -> None: mock_invoke_post_async.return_value = invoke_response() @@ -420,7 +420,7 @@ async def test_langchain_tool_forwards_timeout(self, mock_invoke_post_async: Asy assert body.timeout == 60 @mark.parametrize("stage_version", [None, 1, 2]) - @patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) + @patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_langchain_tool_forwards_stage_version( self, mock_invoke_post_async: AsyncMock, stage_version: int | None @@ -435,7 +435,7 @@ async def test_langchain_tool_forwards_stage_version( assert body.stage_version == stage_version -@patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) +@patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_invoke_with_rulesets(mock_invoke_post_async: Mock) -> None: mock_invoke_post_async.return_value = invoke_response() @@ -460,7 +460,7 @@ async def test_invoke_with_rulesets(mock_invoke_post_async: Mock) -> None: assert "rulesets" not in body.additional_properties -@patch("galileo.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) +@patch("splunk_ao.protect.invoke_protect_invoke_post.asyncio", new_callable=AsyncMock) @mark.asyncio async def test_invoke_api_validation_error(mock_invoke_post_async: Mock) -> None: error_detail_item = {"loc": ["body", "payload", "input"], "msg": "Field required", "type": "missing"} diff --git a/tests/test_protect_parser.py b/tests/test_protect_parser.py index 626aee7f..db9a6f32 100644 --- a/tests/test_protect_parser.py +++ b/tests/test_protect_parser.py @@ -7,7 +7,7 @@ from langchain_core.language_models.llms import LLM from pytest import LogCaptureFixture, mark -from galileo.handlers.langchain.tool import ProtectParser +from splunk_ao.handlers.langchain.tool import ProtectParser A_TRACE_METADATA_DICT = { "trace_metadata": { @@ -82,7 +82,7 @@ def test_echo(echo_output: bool, should_log: bool, caplog: LogCaptureFixture, en """Verify that the ProtectParser echoes the output if echo_output is True.""" parser = ProtectParser(chain=ProtectLLM(), echo_output=echo_output) - with caplog.at_level(logging.DEBUG, logger="galileo.handlers.langchain.tool"): + with caplog.at_level(logging.DEBUG, logger="splunk_ao.handlers.langchain.tool"): parser.parser(dumps({"text": "foo", "status": "not_triggered", **A_TRACE_METADATA_DICT})) if should_log: diff --git a/tests/test_public_imports.py b/tests/test_public_imports.py index 27acc3ec..c6a6eb6a 100644 --- a/tests/test_public_imports.py +++ b/tests/test_public_imports.py @@ -1,10 +1,10 @@ -"""Ensure types advertised in the code-metric system prompt are importable from `galileo`. +"""Ensure types advertised in the code-metric system prompt are importable from `splunk_ao`. If any of these break, the autogenerated scorer prompt will tell the LLM to import a type that doesn't exist, causing NameError at scorer runtime. """ -import galileo +import splunk_ao def test_scorer_prompt_types_are_exported(): @@ -20,5 +20,5 @@ def test_scorer_prompt_types_are_exported(): "Document", "SplunkAOMetrics", ] - missing = [name for name in types if not hasattr(galileo, name)] - assert not missing, f"Types missing from `galileo` public API: {missing}" + missing = [name for name in types if not hasattr(splunk_ao, name)] + assert not missing, f"Types missing from `splunk_ao` public API: {missing}" diff --git a/tests/test_query_result.py b/tests/test_query_result.py index 9de59056..9c3ba27e 100644 --- a/tests/test_query_result.py +++ b/tests/test_query_result.py @@ -4,8 +4,8 @@ from galileo.resources.models import LogRecordsQueryResponse from galileo.resources.types import UNSET -from galileo.search import RecordType -from galileo.shared.query_result import QueryResult, _flatten_dict +from splunk_ao.search import RecordType +from splunk_ao.shared.query_result import QueryResult, _flatten_dict @pytest.mark.parametrize( diff --git a/tests/test_runs.py b/tests/test_runs.py index 710d9bf0..349dbecb 100644 --- a/tests/test_runs.py +++ b/tests/test_runs.py @@ -5,14 +5,14 @@ import pytest from galileo.resources.models import HTTPValidationError, RunScorerSettingsResponse, ScorerConfig, ValidationError -from galileo.runs import update_scorer_settings +from splunk_ao.runs import update_scorer_settings FIXED_PROJECT_ID = str(uuid4()) FIXED_RUN_ID = str(uuid4()) class TestUpdateScorerSettings: - @patch("galileo.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") + @patch("splunk_ao.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") def test_successful_call(self, mock_api_call): mock_response = Mock(spec=RunScorerSettingsResponse) mock_api_call.return_value = mock_response @@ -29,7 +29,7 @@ def test_successful_call(self, mock_api_call): assert body.scorers == mock_scorers assert response == mock_response - @patch("galileo.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") + @patch("splunk_ao.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") def test_api_failure_raises_value_error(self, mock_api_call): mock_api_call.return_value = None mock_scorers = [Mock(spec=ScorerConfig)] @@ -39,7 +39,7 @@ def test_api_failure_raises_value_error(self, mock_api_call): mock_api_call.assert_called_once() - @patch("galileo.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") + @patch("splunk_ao.runs.upsert_scorers_config_projects_project_id_runs_run_id_scorer_settings_patch.sync") def test_http_validation_error_raises_exception(self, mock_api_call): detail = [ValidationError(loc=["body", "project_id"], msg="value is not a valid uuid", type_="type_error.uuid")] mock_api_call.return_value = HTTPValidationError(detail=detail) diff --git a/tests/test_scorers.py b/tests/test_scorers.py index 95cee5ff..3dc8ee5d 100644 --- a/tests/test_scorers.py +++ b/tests/test_scorers.py @@ -1,16 +1,15 @@ import uuid from unittest.mock import ANY, Mock, patch -from src.galileo.resources.models.base_scorer_version_response import BaseScorerVersionResponse - from galileo.resources.models import ( + BaseScorerVersionResponse, ListScorersRequest, ListScorersResponse, ScorerTypeFilter, ScorerTypeFilterOperator, ScorerTypes, ) -from galileo.scorers import Scorers +from splunk_ao.scorers import Scorers def list_scorers_all(): @@ -50,7 +49,7 @@ def list_scorers_all(): ) -@patch("galileo.scorers.list_scorers_with_filters_scorers_list_post") +@patch("splunk_ao.scorers.list_scorers_with_filters_scorers_list_post") def test_list_all_scorers(list_scorers_mock: Mock) -> None: list_scorers_mock.sync.return_value = list_scorers_all() results = Scorers().list() @@ -61,7 +60,7 @@ def test_list_all_scorers(list_scorers_mock: Mock) -> None: list_scorers_mock.sync.assert_called_once_with(client=ANY, body=ListScorersRequest(filters=[]), starting_token=0) -@patch("galileo.scorers.list_scorers_with_filters_scorers_list_post") +@patch("splunk_ao.scorers.list_scorers_with_filters_scorers_list_post") def test_list_all_scorers_preset_filter(list_scorers_mock: Mock) -> None: list_scorers_mock.sync.return_value = ListScorersResponse(scorers=[]) Scorers().list(types=[ScorerTypes.LLM]) @@ -74,7 +73,7 @@ def test_list_all_scorers_preset_filter(list_scorers_mock: Mock) -> None: ) -@patch("galileo.scorers.list_scorers_with_filters_scorers_list_post") +@patch("splunk_ao.scorers.list_scorers_with_filters_scorers_list_post") def test_list_all_scorers_paginated(list_scorers_mock: Mock) -> None: # Mock the first page of the response page1_response = ListScorersResponse.from_dict( @@ -172,7 +171,7 @@ def __init__(self, status_code): super().__init__(f"HTTP Error: {status_code}") -@patch("galileo.scorers.get_scorer_version_or_latest_scorers_scorer_id_version_get") +@patch("splunk_ao.scorers.get_scorer_version_or_latest_scorers_scorer_id_version_get") def test_get_scorer_version_success(get_scorer_version_mock: Mock) -> None: # Setup mock_response = create_mock_version_response() @@ -196,7 +195,7 @@ def test_get_scorer_version_success(get_scorer_version_mock: Mock) -> None: assert result.registered_scorer is None -@patch("galileo.scorers.list_scorers_with_filters_scorers_list_post") +@patch("splunk_ao.scorers.list_scorers_with_filters_scorers_list_post") def test_list_with_multiple_types(mock_list_scorers: Mock) -> None: """Test that listing scorers with multiple types uses the ONE_OF operator.""" mock_list_scorers.sync.return_value = ListScorersResponse(scorers=[]) diff --git a/tests/test_search.py b/tests/test_search.py index 17f84568..17146dd0 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -5,7 +5,7 @@ import pytest from galileo.resources.models import HTTPValidationError, LogRecordsQueryResponse, ValidationError -from galileo.search import get_sessions, get_spans, get_traces +from splunk_ao.search import get_sessions, get_spans, get_traces FIXED_PROJECT_ID = str(uuid4()) @@ -17,9 +17,9 @@ def _log_records_query_response_factory(records: list) -> LogRecordsQueryRespons @pytest.mark.parametrize( "test_function, patch_target", [ - (get_spans, "galileo.search.query_spans_projects_project_id_spans_search_post.sync"), - (get_traces, "galileo.search.query_traces_projects_project_id_traces_search_post.sync"), - (get_sessions, "galileo.search.query_sessions_projects_project_id_sessions_search_post.sync"), + (get_spans, "splunk_ao.search.query_spans_projects_project_id_spans_search_post.sync"), + (get_traces, "splunk_ao.search.query_traces_projects_project_id_traces_search_post.sync"), + (get_sessions, "splunk_ao.search.query_sessions_projects_project_id_sessions_search_post.sync"), ], ) class TestSearchHelpers: diff --git a/tests/test_sort.py b/tests/test_sort.py index 481ce496..248c70af 100644 --- a/tests/test_sort.py +++ b/tests/test_sort.py @@ -3,7 +3,7 @@ import pytest from galileo.resources.models import LogRecordsSortClause -from galileo.shared.sort import Sort, sort +from splunk_ao.shared.sort import Sort, sort class TestSort: diff --git a/tests/test_stages.py b/tests/test_stages.py index f9a9f065..eeb2c5b0 100644 --- a/tests/test_stages.py +++ b/tests/test_stages.py @@ -6,16 +6,16 @@ from galileo.resources.models import HTTPValidationError from galileo.resources.models.stage_db import StageDB as APIStageDB -from galileo.stages import ( +from galileo_core.schemas.protect.rule import Rule, RuleOperator +from galileo_core.schemas.protect.ruleset import Ruleset +from galileo_core.schemas.protect.stage import StageDB, StageType +from splunk_ao.stages import ( create_protect_stage, get_protect_stage, pause_protect_stage, resume_protect_stage, update_protect_stage, ) -from galileo_core.schemas.protect.rule import Rule, RuleOperator -from galileo_core.schemas.protect.ruleset import Ruleset -from galileo_core.schemas.protect.stage import StageDB, StageType FIXED_PROJECT_ID = uuid.uuid4() FIXED_STAGE_ID = uuid.uuid4() @@ -66,13 +66,13 @@ def _core_stage_db_factory( @pytest.fixture(autouse=True) def _patch_common_modules(): """Patch common external deps once for the whole module.""" - with patch("galileo.stages.Projects") as proj_patch: + with patch("splunk_ao.stages.Projects") as proj_patch: proj_patch.return_value.get_with_env_fallbacks.return_value.id = str(FIXED_PROJECT_ID) yield -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") -@patch("galileo.stages.ts_name", return_value="auto-name") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.ts_name", return_value="auto-name") def test_create_stage_happy_path(mock_ts_name: Mock, mock_api: Mock) -> None: """Smoke-test: minimal args produce StageDB and correct API call.""" mock_api.return_value = _api_stage_db_factory(name="auto-name") @@ -84,7 +84,7 @@ def test_create_stage_happy_path(mock_ts_name: Mock, mock_api: Mock) -> None: assert stage.project_id == FIXED_PROJECT_ID -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") def test_create_stage_validation_error(mock_api: Mock) -> None: """create_stage returns HTTPValidationError untouched.""" err = HTTPValidationError(detail=[{"msg": "bad", "loc": ["body"], "type": "value_error"}]) @@ -94,8 +94,8 @@ def test_create_stage_validation_error(mock_api: Mock) -> None: assert res is err -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") -@patch("galileo.stages.ts_name", return_value="ts_auto") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.ts_name", return_value="ts_auto") def test_create_stage_generates_name_and_type(mock_ts_name: Mock, mock_api: Mock) -> None: """No name provided → ts_name used; stage_type override respected.""" mock_api.return_value = _api_stage_db_factory(name="ts_auto", stage_type=StageType.central, paused=True) @@ -110,7 +110,7 @@ def test_create_stage_generates_name_and_type(mock_ts_name: Mock, mock_api: Mock assert stage.paused is True -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") def test_create_central_stage_with_rulesets(mock_api: Mock) -> None: rules = [Rule(metric="m1", operator=RuleOperator.eq, target_value="v1")] rulesets = [Ruleset(rules=rules)] @@ -139,7 +139,7 @@ def test_create_central_stage_with_rulesets(mock_api: Mock) -> None: assert "rulesets" not in body.additional_properties -@patch("galileo.stages.get_stage_projects_project_id_stages_get.sync") +@patch("splunk_ao.stages.get_stage_projects_project_id_stages_get.sync") def test_get_stage_by_id(mock_api: Mock) -> None: mock_api.return_value = _api_stage_db_factory(stage_id=FIXED_STAGE_ID) @@ -152,8 +152,8 @@ def test_get_stage_by_id(mock_api: Mock) -> None: assert stage.id == FIXED_STAGE_ID -@patch("galileo.stages.get_stage_projects_project_id_stages_get.sync") -@patch("galileo.stages.Projects") +@patch("splunk_ao.stages.get_stage_projects_project_id_stages_get.sync") +@patch("splunk_ao.stages.Projects") def test_get_stage_by_names(mock_projects_cls: Mock, mock_api: Mock) -> None: proj_inst = Mock() proj_inst.get_with_env_fallbacks.return_value.id = str(FIXED_PROJECT_ID) @@ -170,8 +170,8 @@ def test_get_stage_by_names(mock_projects_cls: Mock, mock_api: Mock) -> None: assert stage.name == "named-stage" -@patch("galileo.stages.update_stage_projects_project_id_stages_stage_id_post.sync") -@patch("galileo.stages.Stages.get") +@patch("splunk_ao.stages.update_stage_projects_project_id_stages_stage_id_post.sync") +@patch("splunk_ao.stages.Stages.get") def test_update_stage_rulesets(mock_get: Mock, mock_api: Mock) -> None: """Verify rulesets payload reaches API, version bumps.""" mock_get.return_value = _core_stage_db_factory(stage_id=FIXED_STAGE_ID) @@ -191,9 +191,9 @@ def test_update_stage_rulesets(mock_get: Mock, mock_api: Mock) -> None: assert stage.version == 2 -@patch("galileo.stages.update_stage_projects_project_id_stages_stage_id_post.sync") -@patch("galileo.stages.Stages.get") -@patch("galileo.stages.Projects") +@patch("splunk_ao.stages.update_stage_projects_project_id_stages_stage_id_post.sync") +@patch("splunk_ao.stages.Stages.get") +@patch("splunk_ao.stages.Projects") def test_update_stage_by_names(mock_projects_cls: Mock, mock_get: Mock, mock_api: Mock) -> None: proj_inst = Mock() proj_inst.get_with_env_fallbacks.return_value.id = str(FIXED_PROJECT_ID) @@ -211,8 +211,8 @@ def test_update_stage_by_names(mock_projects_cls: Mock, mock_get: Mock, mock_api @pytest.mark.parametrize(("pause_flag", "api_fn"), [(True, pause_protect_stage), (False, resume_protect_stage)]) -@patch("galileo.stages.pause_stage_projects_project_id_stages_stage_id_put.sync") -@patch("galileo.stages.Stages.get") +@patch("splunk_ao.stages.pause_stage_projects_project_id_stages_stage_id_put.sync") +@patch("splunk_ao.stages.Stages.get") def test_pause_and_resume_by_id(mock_get: Mock, mock_api: Mock, pause_flag, api_fn) -> None: mock_get.return_value = _core_stage_db_factory(stage_id=FIXED_STAGE_ID, paused=not pause_flag) mock_api.return_value = _api_stage_db_factory(stage_id=FIXED_STAGE_ID, paused=pause_flag) @@ -225,9 +225,9 @@ def test_pause_and_resume_by_id(mock_get: Mock, mock_api: Mock, pause_flag, api_ assert stage.paused is pause_flag -@patch("galileo.stages.pause_stage_projects_project_id_stages_stage_id_put.sync") -@patch("galileo.stages.Stages.get") -@patch("galileo.stages.Projects") +@patch("splunk_ao.stages.pause_stage_projects_project_id_stages_stage_id_put.sync") +@patch("splunk_ao.stages.Stages.get") +@patch("splunk_ao.stages.Projects") def test_pause_stage_by_names(mock_projects_cls: Mock, mock_get: Mock, mock_api: Mock) -> None: proj_inst = Mock() proj_inst.get_with_env_fallbacks.return_value.id = str(FIXED_PROJECT_ID) @@ -246,7 +246,7 @@ def test_pause_stage_by_names(mock_projects_cls: Mock, mock_get: Mock, mock_api: assert stage.paused is True -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") def test_stage_creation_with_project_id_and_project_name_env_var(mock_api: Mock, monkeypatch) -> None: monkeypatch.setenv("SPLUNK_AO_PROJECT", "proj") @@ -278,7 +278,7 @@ def test_stage_creation_with_project_id_and_project_name_env_var(mock_api: Mock, assert "rulesets" not in body.additional_properties -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") def test_stage_creation_with_project_id_and_project_id_env_var(mock_api: Mock, monkeypatch) -> None: monkeypatch.setenv("SPLUNK_AO_PROJECT_ID", str(FIXED_PROJECT_ID)) @@ -310,7 +310,7 @@ def test_stage_creation_with_project_id_and_project_id_env_var(mock_api: Mock, m assert "rulesets" not in body.additional_properties -@patch("galileo.stages.create_stage_projects_project_id_stages_post.sync") +@patch("splunk_ao.stages.create_stage_projects_project_id_stages_post.sync") def test_stage_creation_with_project_name_and_project_id_env_var(mock_api: Mock, monkeypatch) -> None: monkeypatch.setenv("SPLUNK_AO_PROJECT_ID", "proj") diff --git a/tests/test_thread_pool_task_handler.py b/tests/test_thread_pool_task_handler.py index 4f178ac1..e5080bf4 100644 --- a/tests/test_thread_pool_task_handler.py +++ b/tests/test_thread_pool_task_handler.py @@ -2,7 +2,7 @@ from unittest.mock import Mock, patch import pytest -from src.galileo.logger.task_handler import ThreadPoolTaskHandler +from src.splunk_ao.logger.task_handler import ThreadPoolTaskHandler class TestThreadPoolTaskHandler: @@ -11,7 +11,7 @@ class TestThreadPoolTaskHandler: @pytest.fixture def mock_pool(self): """Mock EventLoopThreadPool.""" - with patch("src.galileo.logger.task_handler.EventLoopThreadPool") as mock_pool_class: + with patch("src.splunk_ao.logger.task_handler.EventLoopThreadPool") as mock_pool_class: mock_pool = Mock() mock_pool_class.return_value = mock_pool yield mock_pool diff --git a/tests/test_traces_client_headers.py b/tests/test_traces_client_headers.py index de67257e..d70a997a 100644 --- a/tests/test_traces_client_headers.py +++ b/tests/test_traces_client_headers.py @@ -4,9 +4,9 @@ import pytest -from galileo.traces import Traces -from galileo.utils.headers_data import get_package_version from galileo_core.constants.request_method import RequestMethod +from splunk_ao.traces import Traces +from splunk_ao.utils.headers_data import get_package_version class TestTracesHeaders: @@ -15,7 +15,7 @@ class TestTracesHeaders: @pytest.fixture def mock_config(self): """Mock SplunkAOConfig.""" - with patch("galileo.traces.SplunkAOConfig") as mock_config_class: + with patch("splunk_ao.traces.SplunkAOConfig") as mock_config_class: mock_config = Mock() mock_api_client = Mock() mock_api_client.arequest = AsyncMock(return_value={"status": "ok"}) @@ -46,5 +46,5 @@ async def test_make_async_request_includes_sdk_header(self, traces_client, mock_ # The header should include version and dynamic method name from get_method_name() header_value = content_headers["X-Galileo-SDK"] assert header_value.startswith(f"galileo-python/{get_package_version()}") - # Should contain the method name (e.g., "_make_async_request@galileo.traces") - assert "@galileo.traces" in header_value + # Should contain the method name (e.g., "_make_async_request@splunk_ao.traces") + assert "@splunk_ao.traces" in header_value diff --git a/tests/test_uuid_utils.py b/tests/test_uuid_utils.py index a1af6ab7..85bd5ab3 100644 --- a/tests/test_uuid_utils.py +++ b/tests/test_uuid_utils.py @@ -6,7 +6,7 @@ import pytest -from galileo.utils.uuid_utils import convert_uuid_if_uuid7, uuid7_to_uuid4 +from splunk_ao.utils.uuid_utils import convert_uuid_if_uuid7, uuid7_to_uuid4 @pytest.fixture diff --git a/tests/testutils/setup.py b/tests/testutils/setup.py index 4524f156..c27c1454 100644 --- a/tests/testutils/setup.py +++ b/tests/testutils/setup.py @@ -8,13 +8,13 @@ from pydantic import BaseModel -from galileo.log_streams import LogStream -from galileo.logger.logger import SplunkAOLogger -from galileo.projects import Project from galileo.resources.models import ExperimentResponse, ProjectType from galileo.resources.models.log_stream_response import LogStreamResponse from galileo.resources.models.project_create_response import ProjectCreateResponse from galileo.resources.models.task_type import TaskType +from splunk_ao.log_streams import LogStream +from splunk_ao.logger.logger import SplunkAOLogger +from splunk_ao.projects import Project class ThreadPoolTaskInfo(BaseModel): diff --git a/tests/utils/test_datasets.py b/tests/utils/test_datasets.py index 8a832473..57a2b6c1 100644 --- a/tests/utils/test_datasets.py +++ b/tests/utils/test_datasets.py @@ -5,8 +5,8 @@ from galileo.resources.models.dataset_content import DatasetContent from galileo.resources.models.dataset_row import DatasetRow from galileo.resources.models.dataset_row_values_dict import DatasetRowValuesDict -from galileo.schema.datasets import DatasetRecord -from galileo.utils.datasets import ( +from splunk_ao.schema.datasets import DatasetRecord +from splunk_ao.utils.datasets import ( create_rows_from_records, get_dataset_and_records, get_records_for_dataset, @@ -15,8 +15,8 @@ ) -@patch("galileo.datasets.get_dataset") -@patch("galileo.utils.datasets.get_records_for_dataset", return_value=[]) +@patch("splunk_ao.datasets.get_dataset") +@patch("splunk_ao.utils.datasets.get_records_for_dataset", return_value=[]) def test_get_dataset_and_records_with_id(mock_get_records, mock_get_dataset, dataset_content) -> None: """Test _get_dataset_and_records function with dataset_id.""" # Setup @@ -33,8 +33,8 @@ def test_get_dataset_and_records_with_id(mock_get_records, mock_get_dataset, dat mock_get_records.assert_called_once_with(mock_dataset) -@patch("galileo.datasets.get_dataset") -@patch("galileo.utils.datasets.get_records_for_dataset", return_value=[]) +@patch("splunk_ao.datasets.get_dataset") +@patch("splunk_ao.utils.datasets.get_records_for_dataset", return_value=[]) def test_get_dataset_and_records_with_name(mock_get_records, mock_get_dataset, dataset_content) -> None: """Test _get_dataset_and_records function with dataset_name.""" # Setup @@ -51,7 +51,7 @@ def test_get_dataset_and_records_with_name(mock_get_records, mock_get_dataset, d mock_get_records.assert_called_once_with(mock_dataset) -@patch("galileo.datasets.get_dataset") +@patch("splunk_ao.datasets.get_dataset") def test_get_dataset_and_records_not_found_id(mock_get_dataset) -> None: """Test _get_dataset_and_records function when dataset with id is not found.""" # Setup @@ -62,7 +62,7 @@ def test_get_dataset_and_records_not_found_id(mock_get_dataset) -> None: get_dataset_and_records(id="test-id") -@patch("galileo.datasets.get_dataset") +@patch("splunk_ao.datasets.get_dataset") def test_get_dataset_and_records_not_found_name(mock_get_dataset) -> None: """Test _get_dataset_and_records function when dataset with name is not found.""" # Setup @@ -80,7 +80,7 @@ def test_get_dataset_and_records_no_params() -> None: get_dataset_and_records() -@patch("galileo.datasets.convert_dataset_row_to_record") +@patch("splunk_ao.datasets.convert_dataset_row_to_record") def test_get_records_for_dataset(mock_convert, dataset_content) -> None: """Test _get_records_for_dataset function.""" # Setup @@ -109,7 +109,7 @@ def test_get_records_for_dataset_no_content() -> None: get_records_for_dataset(mock_dataset) -@patch("galileo.utils.datasets.DatasetRecord") +@patch("splunk_ao.utils.datasets.DatasetRecord") def test_create_rows_from_records_with_input_field(mock_dataset_record) -> None: """Test create_rows_from_records function with records containing 'input' field.""" # Setup @@ -124,7 +124,7 @@ def test_create_rows_from_records_with_input_field(mock_dataset_record) -> None: assert result == ["record instance"] -@patch("galileo.utils.datasets.DatasetRecord") +@patch("splunk_ao.utils.datasets.DatasetRecord") def test_create_rows_from_records_without_input_field(mock_dataset_record) -> None: """Test create_rows_from_records function with records not containing 'input' field.""" # Setup @@ -139,7 +139,7 @@ def test_create_rows_from_records_without_input_field(mock_dataset_record) -> No assert result == ["record instance"] -@patch("galileo.utils.datasets.DatasetRecord") +@patch("splunk_ao.utils.datasets.DatasetRecord") def test_create_rows_from_records_with_dict_without_input_field(mock_dataset_record) -> None: """Test create_rows_from_records function with dict records not containing 'input' field.""" # Setup @@ -154,7 +154,7 @@ def test_create_rows_from_records_with_dict_without_input_field(mock_dataset_rec assert result == ["record instance"] -@patch("galileo.utils.datasets.DatasetRecord") +@patch("splunk_ao.utils.datasets.DatasetRecord") def test_create_rows_from_records_mixed_types(mock_dataset_record) -> None: """Test create_rows_from_records function with mixed record types.""" # Setup @@ -172,7 +172,7 @@ def test_create_rows_from_records_mixed_types(mock_dataset_record) -> None: assert result == ["record 1", "record 2", "record 3"] -@patch("galileo.utils.datasets.get_dataset_and_records") +@patch("splunk_ao.utils.datasets.get_dataset_and_records") def test_load_dataset_and_records_with_dataset_id(mock_get_dataset_and_records) -> None: """Test load_dataset_and_records function with dataset_id.""" # Setup @@ -189,7 +189,7 @@ def test_load_dataset_and_records_with_dataset_id(mock_get_dataset_and_records) assert records == mock_records -@patch("galileo.utils.datasets.get_dataset_and_records") +@patch("splunk_ao.utils.datasets.get_dataset_and_records") def test_load_dataset_and_records_with_dataset_name(mock_get_dataset_and_records) -> None: """Test load_dataset_and_records function with dataset_name.""" # Setup @@ -206,7 +206,7 @@ def test_load_dataset_and_records_with_dataset_name(mock_get_dataset_and_records assert records == mock_records -@patch("galileo.utils.datasets.get_dataset_and_records") +@patch("splunk_ao.utils.datasets.get_dataset_and_records") def test_load_dataset_and_records_with_dataset_as_string(mock_get_dataset_and_records) -> None: """Test load_dataset_and_records function with dataset as string.""" # Setup @@ -223,11 +223,11 @@ def test_load_dataset_and_records_with_dataset_as_string(mock_get_dataset_and_re assert records == mock_records -@patch("galileo.utils.datasets.get_records_for_dataset") +@patch("splunk_ao.utils.datasets.get_records_for_dataset") def test_load_dataset_and_records_with_dataset_object(mock_get_records) -> None: """Test load_dataset_and_records function with Dataset object.""" # Setup - from galileo.datasets import Dataset + from splunk_ao.datasets import Dataset mock_dataset = Mock(spec=Dataset) mock_records = [DatasetRecord(input="test")] @@ -242,7 +242,7 @@ def test_load_dataset_and_records_with_dataset_object(mock_get_records) -> None: assert records == mock_records -@patch("galileo.utils.datasets.create_rows_from_records") +@patch("splunk_ao.utils.datasets.create_rows_from_records") def test_load_dataset_and_records_with_records_list(mockcreate_rows) -> None: """Test load_dataset_and_records function with list of records.""" # Setup diff --git a/tests/utils/test_exception_handling.py b/tests/utils/test_exception_handling.py index 3819ad8d..fc449536 100644 --- a/tests/utils/test_exception_handling.py +++ b/tests/utils/test_exception_handling.py @@ -6,14 +6,14 @@ import httpx import pytest -from galileo.utils.decorators import ( +from galileo_core.exceptions.http import GalileoHTTPException +from splunk_ao.utils.decorators import ( INFRASTRUCTURE_EXCEPTIONS, RETRYABLE_STATUS_CODES, async_warn_catch_exception, retry_on_transient_http_error, warn_catch_exception, ) -from galileo_core.exceptions.http import GalileoHTTPException class TestWarnCatchException: diff --git a/tests/utils/test_metrics.py b/tests/utils/test_metrics.py index b156f6d6..346be010 100644 --- a/tests/utils/test_metrics.py +++ b/tests/utils/test_metrics.py @@ -2,11 +2,11 @@ import pytest -from galileo.schema.metrics import LocalMetricConfig -from galileo.utils.metrics import _populate_local_metric, populate_local_metrics from galileo_core.schemas.logging.span import LlmSpan, WorkflowSpan from galileo_core.schemas.logging.step import StepType from galileo_core.schemas.logging.trace import Trace +from splunk_ao.schema.metrics import LocalMetricConfig +from splunk_ao.utils.metrics import _populate_local_metric, populate_local_metrics # Define simple scorer and aggregator functions for testing diff --git a/tests/utils/test_serialization.py b/tests/utils/test_serialization.py index 6885c203..300b2ef7 100644 --- a/tests/utils/test_serialization.py +++ b/tests/utils/test_serialization.py @@ -14,7 +14,7 @@ from langchain_core.messages import AIMessage, HumanMessage from pydantic import BaseModel -from galileo.utils.serialization import ( +from splunk_ao.utils.serialization import ( EventSerializer, _convert_langchain_content_block, _normalize_multimodal_content, @@ -874,7 +874,7 @@ class ModelWithoutSchema(BaseModel): name: str # Mock the hasattr check to return False for model_json_schema being callable - with patch("galileo.utils.serialization.callable") as mock_callable: + with patch("splunk_ao.utils.serialization.callable") as mock_callable: mock_callable.return_value = False serializer = EventSerializer() diff --git a/tests/utils/test_telemetry_toggle.py b/tests/utils/test_telemetry_toggle.py index fd13f9ae..672ee3eb 100644 --- a/tests/utils/test_telemetry_toggle.py +++ b/tests/utils/test_telemetry_toggle.py @@ -1,4 +1,4 @@ -from galileo.utils.decorators import galileo_logging_enabled +from splunk_ao.utils.decorators import galileo_logging_enabled def test_galileo_logging_enabled(monkeypatch) -> None: diff --git a/tests/utils/test_validations.py b/tests/utils/test_validations.py index e3a2f83c..83168816 100644 --- a/tests/utils/test_validations.py +++ b/tests/utils/test_validations.py @@ -1,6 +1,6 @@ import pytest -from galileo.utils.validations import ValidationError, require_exactly_one +from splunk_ao.utils.validations import ValidationError, require_exactly_one class TestRequireExactlyOne: