Skip to content

Commit

Permalink
Merge pull request #19442 from nsoranzo/type_annot
Browse files Browse the repository at this point in the history
Type annotations improvements
  • Loading branch information
nsoranzo authored Jan 23, 2025
2 parents 42f190e + a79f518 commit e2636d7
Show file tree
Hide file tree
Showing 23 changed files with 83 additions and 68 deletions.
12 changes: 6 additions & 6 deletions lib/galaxy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def _configure_toolbox(self):
self.citations_manager = CitationsManager(self)
self.biotools_metadata_source = get_galaxy_biotools_metadata_source(self.config)

self.dynamic_tools_manager = DynamicToolManager(self)
self.dynamic_tool_manager = DynamicToolManager(self)
self._toolbox_lock = threading.RLock()
self._toolbox = tools.ToolBox(self.config.tool_configs, self.config.tool_path, self)
galaxy_root_dir = os.path.abspath(self.config.root)
Expand Down Expand Up @@ -565,7 +565,7 @@ def _shutdown_model(self):
self.model.engine.dispose()


class GalaxyManagerApplication(MinimalManagerApp, MinimalGalaxyApplication, InstallationTarget[tools.ToolBox]):
class GalaxyManagerApplication(MinimalManagerApp, MinimalGalaxyApplication):
"""Extends the MinimalGalaxyApplication with most managers that are not tied to a web or job handling context."""

model: GalaxyModelMapping
Expand Down Expand Up @@ -662,9 +662,6 @@ def __init__(self, configure_logging=True, use_converters=True, use_display_appl
# We need the datatype registry for running certain tasks that modify HDAs, and to build the registry we need
# to setup the installed repositories ... this is not ideal
self._configure_tool_config_files()
self.installed_repository_manager = self._register_singleton(
InstalledRepositoryManager, InstalledRepositoryManager(self)
)
self.dynamic_tool_manager = self._register_singleton(DynamicToolManager)
self.trs_proxy = self._register_singleton(TrsProxy, TrsProxy(self.config))
self._configure_datatypes_registry(
Expand Down Expand Up @@ -713,7 +710,7 @@ def is_job_handler(self) -> bool:
) or not self.config.track_jobs_in_database


class UniverseApplication(StructuredApp, GalaxyManagerApplication):
class UniverseApplication(StructuredApp, GalaxyManagerApplication, InstallationTarget[tools.ToolBox]):
"""Encapsulates the state of a Universe application"""

model: GalaxyModelMapping
Expand Down Expand Up @@ -775,6 +772,9 @@ def __init__(self, **kwargs) -> None:
self._configure_toolbox()
# Load Data Manager
self.data_managers = self._register_singleton(DataManagers)
self.installed_repository_manager = self._register_singleton(
InstalledRepositoryManager, InstalledRepositoryManager(self)
)
# Load the update repository manager.
self.update_repository_manager = self._register_singleton(
UpdateRepositoryManager, UpdateRepositoryManager(self)
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/app_unittest_utils/galaxy_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def toolbox(self, toolbox: ToolBox):
def wait_for_toolbox_reload(self, toolbox):
# TODO: If the tpm test case passes, does the operation really
# need to wait.
return True
return

def reindex_tool_search(self) -> None:
raise NotImplementedError
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/managers/hdcas.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def set_collection_attributes(dataset_element, *payload):

# TODO: to DatasetCollectionInstanceManager
class HDCAManager(
base.ModelManager,
base.ModelManager[model.HistoryDatasetCollectionAssociation],
secured.AccessibleManagerMixin,
secured.OwnableManagerMixin,
deletable.PurgableManagerMixin,
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/managers/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from galaxy.managers.base import OrmFilterParsersType


class DynamicToolManager(ModelManager):
class DynamicToolManager(ModelManager[model.DynamicTool]):
"""Manages dynamic tools stored in Galaxy's database."""

model_class = model.DynamicTool
Expand Down
7 changes: 5 additions & 2 deletions lib/galaxy/managers/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
joinedload,
subqueryload,
)
from typing_extensions import Annotated
from typing_extensions import (
Annotated,
TypeAlias,
)

from galaxy import (
exceptions,
Expand Down Expand Up @@ -1827,7 +1830,7 @@ def __module_from_dict(
self.add_item_annotation(sa_session, trans.get_user(), step, annotation)

# Stick this in the step temporarily
DictConnection = Dict[str, Union[int, str]]
DictConnection: TypeAlias = Dict[str, Union[int, str]]
temp_input_connections: Dict[str, Union[List[DictConnection], DictConnection]] = step_dict.get(
"input_connections", {}
)
Expand Down
10 changes: 7 additions & 3 deletions lib/galaxy/queue_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import threading
import time
from inspect import ismodule
from typing import TYPE_CHECKING

from kombu import (
Consumer,
Expand All @@ -31,6 +32,9 @@
logging.getLogger("kombu").setLevel(logging.WARNING)
log = logging.getLogger(__name__)

if TYPE_CHECKING:
from galaxy.structured_app import MinimalManagerApp


def send_local_control_task(app, task, get_response=False, kwargs=None):
"""
Expand Down Expand Up @@ -244,7 +248,7 @@ def rebuild_toolbox_search_index(app, **kwargs):
log.debug("App is not a webapp, not building a search index")


def reload_job_rules(app, **kwargs):
def reload_job_rules(app: "MinimalManagerApp", **kwargs):
reload_timer = util.ExecutionTimer()
for module in job_rule_modules(app):
rules_module_name = module.__name__
Expand All @@ -265,7 +269,7 @@ def reload_tour(app, **kwargs):
log.debug("Tour reloaded")


def __job_rule_module_names(app):
def __job_rule_module_names(app: "MinimalManagerApp"):
rules_module_names = {"galaxy.jobs.rules"}
if app.job_config.dynamic_params is not None:
module_name = app.job_config.dynamic_params.get("rules_module")
Expand All @@ -279,7 +283,7 @@ def __job_rule_module_names(app):
return rules_module_names


def job_rule_modules(app):
def job_rule_modules(app: "MinimalManagerApp"):
rules_module_list = []
for rules_module_name in __job_rule_module_names(app):
rules_module = sys.modules.get(rules_module_name, None)
Expand Down
12 changes: 8 additions & 4 deletions lib/galaxy/structured_app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Typed description of Galaxy's app object."""

import abc
import threading
from typing import (
Any,
Optional,
Expand Down Expand Up @@ -31,7 +32,6 @@
from galaxy.security.idencoding import IdEncodingHelper
from galaxy.security.vault import Vault
from galaxy.tool_shed.cache import ToolShedRepositoryCache
from galaxy.tool_util.data import ToolDataTableManager
from galaxy.tool_util.deps.containers import ContainerFinder
from galaxy.tool_util.deps.views import DependencyResolversView
from galaxy.tool_util.verify import test_data
Expand All @@ -46,11 +46,14 @@
from galaxy.managers.collections import DatasetCollectionManager
from galaxy.managers.hdas import HDAManager
from galaxy.managers.histories import HistoryManager
from galaxy.managers.tools import DynamicToolManager
from galaxy.managers.workflows import (
WorkflowContentsManager,
WorkflowsManager,
)
from galaxy.tool_shed.galaxy_install.client import DataManagersInterface
from galaxy.tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager
from galaxy.tool_util.data import ToolDataTableManager
from galaxy.tools import ToolBox
from galaxy.tools.cache import ToolCache
from galaxy.tools.error_reports import ErrorReports
Expand Down Expand Up @@ -117,12 +120,11 @@ class MinimalManagerApp(MinimalApp):
library_folder_manager: Any # 'galaxy.managers.folders.FolderManager'
library_manager: Any # 'galaxy.managers.libraries.LibraryManager'
role_manager: Any # 'galaxy.managers.roles.RoleManager'
installed_repository_manager: "InstalledRepositoryManager"
user_manager: Any
job_config: "JobConfiguration"
job_manager: Any # galaxy.jobs.manager.JobManager
job_metrics: JobMetrics
dynamic_tool_manager: Any # 'galaxy.managers.tools.DynamicToolManager'
dynamic_tool_manager: "DynamicToolManager"
genomes: "Genomes"
error_reports: "ErrorReports"
notification_manager: Any # 'galaxy.managers.notification.NotificationManager'
Expand All @@ -149,7 +151,9 @@ class StructuredApp(MinimalManagerApp):
"""

amqp_internal_connection_obj: Optional[Connection]
data_managers: "DataManagersInterface"
dependency_resolvers_view: DependencyResolversView
installed_repository_manager: "InstalledRepositoryManager"
container_finder: ContainerFinder
tool_dependency_dir: Optional[str]
test_data_resolver: test_data.TestDataResolver
Expand All @@ -158,11 +162,11 @@ class StructuredApp(MinimalManagerApp):
webhooks_registry: WebhooksRegistry
queue_worker: Any # 'galaxy.queue_worker.GalaxyQueueWorker'
data_provider_registry: Any # 'galaxy.visualization.data_providers.registry.DataProviderRegistry'
tool_data_tables: ToolDataTableManager
tool_cache: "ToolCache"
tool_shed_repository_cache: Optional[ToolShedRepositoryCache]
watchers: "ConfigWatchers"
workflow_scheduling_manager: Any # 'galaxy.workflow.scheduling_manager.WorkflowSchedulingManager'
interactivetool_manager: Any
api_keys_manager: Any # 'galaxy.managers.api_keys.ApiKeyManager'
visualizations_registry: Any # 'galaxy.visualization.plugins.registry.VisualizationsRegistry'
_toolbox_lock: threading.RLock
15 changes: 6 additions & 9 deletions lib/galaxy/tool_shed/galaxy_install/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from typing import (
Any,
Dict,
Generic,
List,
Optional,
runtime_checkable,
TYPE_CHECKING,
TypeVar,
Union,
Expand All @@ -15,15 +15,14 @@
from galaxy.model.base import ModelMapping
from galaxy.model.tool_shed_install import HasToolBox
from galaxy.security.idencoding import IdEncodingHelper
from galaxy.tool_shed.cache import ToolShedRepositoryCache
from galaxy.tool_util.data import (
OutputDataset,
ToolDataTableManager,
)
from galaxy.tool_util.toolbox.base import AbstractToolBox

if TYPE_CHECKING:
import galaxy.tool_shed.metadata.installed_repository_manger
from galaxy.tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager


class DataManagerInterface(Protocol):
Expand All @@ -48,19 +47,17 @@ def get_manager(self, data_manager_id: str) -> Optional[DataManagerInterface]: .
def remove_manager(self, manager_ids: Union[str, List[str]]) -> None: ...


ToolBoxType = TypeVar("ToolBoxType", bound="AbstractToolBox")
ToolBoxType = TypeVar("ToolBoxType", bound="AbstractToolBox", contravariant=True)


class InstallationTarget(HasToolBox, Generic[ToolBoxType]):
@runtime_checkable
class InstallationTarget(HasToolBox, Protocol[ToolBoxType]):
data_managers: DataManagersInterface
install_model: ModelMapping
model: ModelMapping
security: IdEncodingHelper
config: Any
installed_repository_manager: "galaxy.tool_shed.metadata.installed_repository_manger.InstalledRepositoryManager"
watchers: Any # TODO: interface...
installed_repository_manager: "InstalledRepositoryManager"
_toolbox_lock: threading.RLock
tool_shed_repository_cache: Optional[ToolShedRepositoryCache]
tool_data_tables: ToolDataTableManager

def wait_for_toolbox_reload(self, old_toolbox: ToolBoxType) -> None: ...
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@


class InstalledRepositoryMetadataManager(GalaxyMetadataGenerator):
app: InstallationTarget

def __init__(
self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import logging
import os
from typing import TYPE_CHECKING
from urllib.error import HTTPError
from urllib.parse import (
urlencode,
Expand All @@ -17,7 +18,6 @@
)

from galaxy.model.base import transaction
from galaxy.tool_shed.galaxy_install import installed_repository_manager
from galaxy.tool_shed.galaxy_install.tools import tool_panel_manager
from galaxy.tool_shed.util import repository_util
from galaxy.tool_shed.util.container_util import get_components_from_key
Expand All @@ -35,11 +35,14 @@
encoding_util,
)

if TYPE_CHECKING:
from galaxy.tool_shed.galaxy_install.client import InstallationTarget

log = logging.getLogger(__name__)


class RepositoryDependencyInstallManager:
def __init__(self, app):
def __init__(self, app: "InstallationTarget"):
self.app = app

def build_repository_dependency_relationships(self, repo_info_dicts, tool_shed_repositories):
Expand Down Expand Up @@ -270,7 +273,7 @@ def create_repository_dependency_objects(
log.info(
f"Reactivating deactivated tool_shed_repository '{str(repository_db_record.name)}'."
)
irm = installed_repository_manager.InstalledRepositoryManager(self.app)
irm = self.app.installed_repository_manager
irm.activate_repository(repository_db_record)
# No additional updates to the database record are necessary.
can_update_db_record = False
Expand Down
13 changes: 6 additions & 7 deletions lib/galaxy/tool_shed/metadata/metadata_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,13 +722,12 @@ def _check_elem_for_dep(elems):
if original_valid_tool_dependencies_dict:
# We're generating metadata on an update pulled to a tool shed repository installed
# into a Galaxy instance, so handle changes to tool dependencies appropriately.
installation_target = cast(InstallationTarget, self.app)
irm = installation_target.installed_repository_manager
(
updated_tool_dependency_names,
deleted_tool_dependency_names,
) = irm.handle_existing_tool_dependencies_that_changed_in_update(
self.repository, original_valid_tool_dependencies_dict, rvs.valid_tool_dependencies_dict
assert isinstance(self.app, InstallationTarget)
irm = self.app.installed_repository_manager
assert self.repository
gx_repository = cast(ToolShedRepository, self.repository)
irm.handle_existing_tool_dependencies_that_changed_in_update(
gx_repository, original_valid_tool_dependencies_dict, rvs.valid_tool_dependencies_dict
)
metadata_dict["tool_dependencies"] = rvs.valid_tool_dependencies_dict
if rvs.invalid_tool_dependencies_dict:
Expand Down
5 changes: 5 additions & 0 deletions lib/galaxy/tool_shed/unittest_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
DataManagersInterface,
InstallationTarget,
)
from galaxy.tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager
from galaxy.tool_shed.util.repository_util import get_installed_repository
from galaxy.tool_util.data import (
OutputDataset,
Expand Down Expand Up @@ -221,6 +222,7 @@ def __init__(
)
dependency_dir = target_directory / "_dependencies"
dependency_dir.mkdir()
self.installed_repository_manager = InstalledRepositoryManager(self)

@property
def tool_dependency_dir(self) -> Optional[str]:
Expand All @@ -236,3 +238,6 @@ def reload_toolbox(self):
@property
def toolbox(self) -> TestToolBox:
return self._toolbox

def wait_for_toolbox_reload(self, toolbox):
return
3 changes: 1 addition & 2 deletions lib/galaxy/tool_shed/util/dependency_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os

from galaxy import util
from galaxy.tool_shed.galaxy_install.installed_repository_manager import InstalledRepositoryManager
from galaxy.tool_shed.util import utility_container_manager
from galaxy.util import UNKNOWN
from galaxy.util.tool_shed.common_util import parse_repository_dependency_tuple
Expand Down Expand Up @@ -198,7 +197,7 @@ def populate_containers_dict_from_repository_metadata(self, repository):
them for uninstalled repositories that are being reinstalled.
"""
if metadata := repository.metadata_:
irm = InstalledRepositoryManager(self.app)
irm = self.app.installed_repository_manager
# Handle repository dependencies.
(
installed_repository_dependencies,
Expand Down
5 changes: 3 additions & 2 deletions lib/galaxy/tool_util/cwl/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from typing import (
Dict,
List,
Optional,
overload,
Union,
)
Expand Down Expand Up @@ -531,7 +532,7 @@ class WorkflowProxy:
def __init__(self, workflow, workflow_path=None):
self._workflow = workflow
self._workflow_path = workflow_path
self._step_proxies = None
self._step_proxies: Optional[List[Union[SubworkflowStepProxy, ToolStepProxy]]] = None

@property
def cwl_id(self):
Expand Down Expand Up @@ -562,7 +563,7 @@ def get_outputs_for_label(self, label):

def tool_reference_proxies(self):
"""Fetch tool source definitions for all referenced tools."""
references = []
references: List[ToolProxy] = []
for step in self.step_proxies():
references.extend(step.tool_reference_proxies())
return references
Expand Down
Loading

0 comments on commit e2636d7

Please sign in to comment.