Skip to content

Commit efbf5e1

Browse files
committed
Hoist agent-operations local imports to module level
Per Marius' review on PR 22625 -- Galaxy only uses local imports when there's a real reason (circular dep, optional dep). None of these had one, so they belong at the top of the file alongside the rest.
1 parent bec6b06 commit efbf5e1

2 files changed

Lines changed: 19 additions & 47 deletions

File tree

lib/galaxy/agents/operations.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
Optional,
1111
)
1212

13+
from sqlalchemy import select
14+
1315
from galaxy.managers.context import ProvidesUserContext
1416
from galaxy.managers.hdas import HDAManager
17+
from galaxy.managers.tools import DynamicToolManager
18+
from galaxy.model import UserDynamicToolAssociation
1519
from galaxy.schema import (
1620
FilterQueryParams,
1721
SerializationParams,
@@ -29,6 +33,9 @@
2933
)
3034
from galaxy.schema.workflows import InvokeWorkflowPayload
3135
from galaxy.structured_app import MinimalManagerApp
36+
from galaxy.tool_util_models.dynamic_tool_models import DynamicUnprivilegedToolCreatePayload
37+
from galaxy.webapps.galaxy.services.invocations import InvocationIndexPayload
38+
from galaxy.webapps.galaxy.services.workflows import WorkflowIndexPayload
3239

3340
log = logging.getLogger(__name__)
3441

@@ -152,8 +159,6 @@ def dataset_collections_service(self):
152159
@property
153160
def dynamic_tools_manager(self):
154161
if self._dynamic_tools_manager is None:
155-
from galaxy.managers.tools import DynamicToolManager
156-
157162
self._dynamic_tools_manager = self.app[DynamicToolManager]
158163
return self._dynamic_tools_manager
159164

@@ -438,8 +443,6 @@ def list_workflows(
438443
show_shared: bool = True,
439444
search: str | None = None,
440445
) -> dict[str, Any]:
441-
from galaxy.webapps.galaxy.services.workflows import WorkflowIndexPayload
442-
443446
payload = WorkflowIndexPayload(
444447
limit=limit,
445448
offset=offset,
@@ -525,8 +528,6 @@ def get_invocations(
525528
if history_id:
526529
decoded_history_id = self.trans.security.decode_id(history_id)
527530

528-
from galaxy.webapps.galaxy.services.invocations import InvocationIndexPayload
529-
530531
payload = InvocationIndexPayload(
531532
workflow_id=decoded_workflow_id,
532533
history_id=decoded_history_id,
@@ -897,8 +898,6 @@ def list_user_tools(self, active: bool = True) -> dict[str, Any]:
897898
}
898899

899900
def create_user_tool(self, representation: dict[str, Any]) -> dict[str, Any]:
900-
from galaxy.tool_util_models.dynamic_tool_models import DynamicUnprivilegedToolCreatePayload
901-
902901
user = self.trans.user
903902
if not user:
904903
raise ValueError("User must be authenticated")
@@ -920,10 +919,6 @@ def delete_user_tool(self, uuid: str) -> dict[str, Any]:
920919
return {"uuid": uuid, "deactivated": True}
921920

922921
def run_user_tool(self, history_id: str, tool_uuid: str, inputs: dict[str, Any]) -> dict[str, Any]:
923-
from sqlalchemy import select
924-
925-
from galaxy.model import UserDynamicToolAssociation
926-
927922
user = self.trans.user
928923
if not user:
929924
raise ValueError("User must be authenticated")

test/integration/test_agents.py

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,24 @@
1111
pytest test/integration/test_agents.py -v
1212
"""
1313

14+
import asyncio
1415
import logging
1516
import os
1617

18+
import pytest
19+
from fastmcp import (
20+
Client,
21+
FastMCP,
22+
)
23+
from fastmcp.exceptions import ToolError
24+
25+
from galaxy.agents.operations import AgentOperationsManager
26+
from galaxy.managers.context import ProvidesUserContext
1727
from galaxy.util.unittest_utils import pytestmark_live_llm
28+
from galaxy.webapps.galaxy.api.mcp import get_mcp_app
1829
from galaxy_test.base.populators import (
1930
DatasetPopulator,
31+
TOOL_WITH_SHELL_COMMAND,
2032
WorkflowPopulator,
2133
)
2234
from galaxy_test.driver.integration_util import IntegrationTestCase
@@ -180,9 +192,6 @@ class TestAgentOperationsManagerEncoding(AgentIntegrationTestCase):
180192
"""
181193

182194
def _make_ops(self):
183-
from galaxy.agents.operations import AgentOperationsManager
184-
from galaxy.managers.context import ProvidesUserContext
185-
186195
class MinimalTrans(ProvidesUserContext):
187196
def __init__(self, app):
188197
self._app = app
@@ -285,8 +294,6 @@ def handle_galaxy_config_kwds(cls, config):
285294
config["enable_beta_tool_formats"] = True
286295

287296
def _get_mcp_server(self):
288-
from galaxy.webapps.galaxy.api.mcp import get_mcp_app
289-
290297
http_app = get_mcp_app(self._app)
291298
return http_app.state.mcp_server
292299

@@ -302,8 +309,6 @@ def _setup_udt_user(self, email: str):
302309
return user, api_key
303310

304311
def _run_async(self, coro):
305-
import asyncio
306-
307312
loop = asyncio.new_event_loop()
308313
try:
309314
return loop.run_until_complete(coro)
@@ -312,15 +317,11 @@ def _run_async(self, coro):
312317

313318
def test_mcp_server_initializes(self):
314319
"""MCP server creates a FastMCP instance when enabled."""
315-
from fastmcp import FastMCP
316-
317320
mcp_server = self._get_mcp_server()
318321
assert isinstance(mcp_server, FastMCP)
319322

320323
def test_mcp_tools_registered(self):
321324
"""MCP server advertises all expected tools."""
322-
from fastmcp import Client
323-
324325
mcp_server = self._get_mcp_server()
325326

326327
async def _list():
@@ -350,8 +351,6 @@ async def _list():
350351

351352
def test_mcp_connect_with_valid_key(self):
352353
"""connect() succeeds with a valid API key and returns user + server info."""
353-
from fastmcp import Client
354-
355354
mcp_server = self._get_mcp_server()
356355
api_key = self._get_api_key()
357356

@@ -367,10 +366,6 @@ async def _connect():
367366

368367
def test_mcp_connect_with_invalid_key(self):
369368
"""connect() rejects an invalid API key."""
370-
import pytest
371-
from fastmcp import Client
372-
from fastmcp.exceptions import ToolError
373-
374369
mcp_server = self._get_mcp_server()
375370

376371
async def _connect():
@@ -382,8 +377,6 @@ async def _connect():
382377

383378
def test_mcp_list_histories(self):
384379
"""list_histories() returns a valid response."""
385-
from fastmcp import Client
386-
387380
mcp_server = self._get_mcp_server()
388381
api_key = self._get_api_key()
389382

@@ -398,8 +391,6 @@ async def _list():
398391

399392
def test_mcp_search_tools(self):
400393
"""search_tools() executes and returns a well-formed response."""
401-
from fastmcp import Client
402-
403394
mcp_server = self._get_mcp_server()
404395
api_key = self._get_api_key()
405396

@@ -417,8 +408,6 @@ async def _search():
417408

418409
def test_mcp_list_user_tools_empty(self):
419410
"""list_user_tools() returns an empty list for a user with the role and no UDTs."""
420-
from fastmcp import Client
421-
422411
mcp_server = self._get_mcp_server()
423412
_, api_key = self._setup_udt_user("udt_list_user@test.com")
424413

@@ -434,10 +423,6 @@ async def _list():
434423

435424
def test_mcp_create_user_tool(self):
436425
"""create_user_tool() persists a UDT and returns its uuid."""
437-
from fastmcp import Client
438-
439-
from galaxy_test.base.populators import TOOL_WITH_SHELL_COMMAND
440-
441426
mcp_server = self._get_mcp_server()
442427
_, api_key = self._setup_udt_user("udt_create_user@test.com")
443428

@@ -456,10 +441,6 @@ async def _create():
456441

457442
def test_mcp_delete_user_tool(self):
458443
"""delete_user_tool() deactivates a UDT so list_user_tools no longer returns it."""
459-
from fastmcp import Client
460-
461-
from galaxy_test.base.populators import TOOL_WITH_SHELL_COMMAND
462-
463444
mcp_server = self._get_mcp_server()
464445
_, api_key = self._setup_udt_user("udt_delete_user@test.com")
465446
populator = DatasetPopulator(self._get_interactor(api_key=api_key))
@@ -494,10 +475,6 @@ async def _flow():
494475

495476
def test_mcp_run_user_tool(self):
496477
"""run_user_tool() executes a UDT against an HDA input and produces an output."""
497-
from fastmcp import Client
498-
499-
from galaxy_test.base.populators import TOOL_WITH_SHELL_COMMAND
500-
501478
mcp_server = self._get_mcp_server()
502479
_, api_key = self._setup_udt_user("udt_run_user@test.com")
503480

0 commit comments

Comments
 (0)