From ab2f76c94d89fd9419b1dc0bc5ea606834cdbe2b Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 5 Dec 2023 14:42:17 -0500 Subject: [PATCH] Use utility function for safeguards --- lib/galaxy/managers/workflows.py | 5 +-- lib/galaxy/model/__init__.py | 70 ++++++++---------------------- lib/galaxy/model/store/__init__.py | 13 ++---- lib/galaxy/webapps/base/webapp.py | 6 +-- lib/galaxy/workflow/extract.py | 4 +- lib/galaxy/workflow/modules.py | 6 +-- lib/galaxy/workflow/run.py | 6 +-- lib/galaxy/workflow/run_request.py | 7 +-- test/integration/test_job_files.py | 5 +-- 9 files changed, 36 insertions(+), 86 deletions(-) diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py index 37c7a748981..5c1a1481e6e 100644 --- a/lib/galaxy/managers/workflows.py +++ b/lib/galaxy/managers/workflows.py @@ -35,7 +35,6 @@ from sqlalchemy import ( from sqlalchemy.orm import ( aliased, joinedload, - object_session, Query, subqueryload, ) @@ -67,6 +66,7 @@ from galaxy.model import ( WorkflowInvocationStep, ) from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.model.index_filter_util import ( append_user_filter, raw_text_column_filter, @@ -822,8 +822,7 @@ class WorkflowContentsManager(UsesAnnotations): # Safeguard: workflow was implicitly merged into this Session prior to SQLAlchemy 2.0. # when AT LEAST ONE step in steps belonged to a session. for step in steps: - if step and object_session(step): - object_session(step).add(workflow) + if ensure_object_added_to_session(workflow, object_in_session=step): break comments: List[model.WorkflowComment] = [] diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 492b8d98c1b..02f1e4985f5 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -129,6 +129,7 @@ from galaxy.model.custom_types import ( UUIDType, ) from galaxy.model.database_object_names import NAMING_CONVENTION +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.model.item_attrs import ( get_item_annotation_str, UsesAnnotations, @@ -2471,9 +2472,7 @@ class PostJobAction(Base, RepresentById): self.output_name = output_name self.action_arguments = action_arguments self.workflow_step = workflow_step - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if workflow_step and object_session(workflow_step): - object_session(workflow_step).add(self) + ensure_object_added_to_session(self, object_in_session=workflow_step) class PostJobActionAssociation(Base, RepresentById): @@ -2488,9 +2487,7 @@ class PostJobActionAssociation(Base, RepresentById): def __init__(self, pja, job=None, job_id=None): if job is not None: self.job = job - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if job and object_session(job): - object_session(job).add(self) + ensure_object_added_to_session(self, object_in_session=job) elif job_id is not None: self.job_id = job_id else: @@ -2861,9 +2858,7 @@ class UserNotificationAssociation(Base, RepresentById): def __init__(self, user, notification): self.user = user - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if user and object_session(user): - object_session(user).add(self) + ensure_object_added_to_session(self, object_in_session=user) self.notification = notification @@ -3517,9 +3512,7 @@ class GroupRoleAssociation(Base, RepresentById): def __init__(self, group, role): self.group = group - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if group and object_session(group): - object_session(group).add(self) + ensure_object_added_to_session(self, object_in_session=group) self.role = role @@ -3690,9 +3683,7 @@ class DefaultQuotaAssociation(Base, Dictifiable, RepresentById): assert type in self.types.__members__.values(), "Invalid type" self.type = type self.quota = quota - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if quota and object_session(quota): - object_session(quota).add(self) + ensure_object_added_to_session(self, object_in_session=quota) class DatasetPermissions(Base, RepresentById): @@ -3733,9 +3724,7 @@ class LibraryPermissions(Base, RepresentById): self.action = action if isinstance(library_item, Library): self.library = library_item - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if library_item and object_session(library_item): - object_session(library_item).add(self) + ensure_object_added_to_session(self, object_in_session=library_item) else: raise Exception(f"Invalid Library specified: {library_item.__class__.__name__}") self.role = role @@ -3757,9 +3746,7 @@ class LibraryFolderPermissions(Base, RepresentById): self.action = action if isinstance(library_item, LibraryFolder): self.folder = library_item - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if library_item and object_session(library_item): - object_session(library_item).add(self) + ensure_object_added_to_session(self, object_in_session=library_item) else: raise Exception(f"Invalid LibraryFolder specified: {library_item.__class__.__name__}") self.role = role @@ -3781,9 +3768,7 @@ class LibraryDatasetPermissions(Base, RepresentById): self.action = action if isinstance(library_item, LibraryDataset): self.library_dataset = library_item - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if library_item and object_session(library_item): - object_session(library_item).add(self) + ensure_object_added_to_session(self, object_in_session=library_item) else: raise Exception(f"Invalid LibraryDataset specified: {library_item.__class__.__name__}") self.role = role @@ -4405,11 +4390,7 @@ class DatasetInstance(RepresentById, UsesCreateAndUpdateTime, _HasTable): elif dataset: add_object_to_object_session(self, dataset) self.dataset = dataset - - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if dataset and object_session(dataset): - object_session(dataset).add(self) - + ensure_object_added_to_session(self, object_in_session=dataset) self.parent_id = parent_id @property @@ -7279,9 +7260,7 @@ class GalaxySessionToHistoryAssociation(Base, RepresentById): def __init__(self, galaxy_session, history): self.galaxy_session = galaxy_session - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if galaxy_session and object_session(galaxy_session): - object_session(galaxy_session).add(self) + ensure_object_added_to_session(self, object_in_session=galaxy_session) add_object_to_object_session(self, history) self.history = history @@ -7793,9 +7772,7 @@ class WorkflowStep(Base, RepresentById): conn = WorkflowStepConnection() conn.input_step_input = step_input - # Safeguard: conn was implicitly merged into this Session prior to SQLAlchemy 2.0. - if step_input and object_session(step_input): - object_session(step_input).add(conn) + ensure_object_added_to_session(conn, object_in_session=step_input) conn.output_name = output_name add_object_to_object_session(conn, output_step) conn.output_step = output_step @@ -8077,9 +8054,7 @@ class WorkflowOutput(Base, Serializable): def __init__(self, workflow_step, output_name=None, label=None, uuid=None): self.workflow_step = workflow_step - # Safeguard: self was implicitly merged into this Session prior to SQLAlchemy 2.0. - if object_session(workflow_step): - object_session(workflow_step).add(self) + ensure_object_added_to_session(self, object_in_session=workflow_step) self.output_name = output_name self.label = label self.uuid = get_uuid(uuid) @@ -8468,9 +8443,7 @@ class WorkflowInvocation(Base, UsesCreateAndUpdateTime, Dictifiable, Serializabl # dispatch on actual object and not step type. output_assoc = WorkflowInvocationOutputValue() output_assoc.workflow_invocation = self - # Safeguard: output_assoc was implicitly merged into this Session prior to SQLAlchemy 2.0. - if object_session(self): - object_session(self).add(output_assoc) + ensure_object_added_to_session(output_assoc, object_in_session=self) output_assoc.workflow_output = workflow_output output_assoc.workflow_step = step output_assoc.value = output_object @@ -8478,9 +8451,7 @@ class WorkflowInvocation(Base, UsesCreateAndUpdateTime, Dictifiable, Serializabl elif output_object.history_content_type == "dataset": output_assoc = WorkflowInvocationOutputDatasetAssociation() output_assoc.workflow_invocation = self - # Safeguard: output_assoc was implicitly merged into this Session prior to SQLAlchemy 2.0. - if object_session(self): - object_session(self).add(output_assoc) + ensure_object_added_to_session(output_assoc, object_in_session=self) output_assoc.workflow_output = workflow_output output_assoc.workflow_step = step output_assoc.dataset = output_object @@ -8488,8 +8459,7 @@ class WorkflowInvocation(Base, UsesCreateAndUpdateTime, Dictifiable, Serializabl elif output_object.history_content_type == "dataset_collection": output_assoc = WorkflowInvocationOutputDatasetCollectionAssociation() output_assoc.workflow_invocation = self - if object_session(self): - object_session(self).add(output_assoc) + ensure_object_added_to_session(output_assoc, object_in_session=self) output_assoc.workflow_output = workflow_output output_assoc.workflow_step = step output_assoc.dataset_collection = output_object @@ -8943,18 +8913,14 @@ class WorkflowInvocationStep(Base, Dictifiable, Serializable): if output_object.history_content_type == "dataset": output_assoc = WorkflowInvocationStepOutputDatasetAssociation() output_assoc.workflow_invocation_step = self - # Safeguard: output_assoc was implicitly merged into this Session prior to SQLAlchemy 2.0. - if object_session(self): - object_session(self).add(output_assoc) + ensure_object_added_to_session(output_assoc, object_in_session=self) output_assoc.dataset = output_object output_assoc.output_name = output_name self.output_datasets.append(output_assoc) elif output_object.history_content_type == "dataset_collection": output_assoc = WorkflowInvocationStepOutputDatasetCollectionAssociation() output_assoc.workflow_invocation_step = self - # Safeguard: output_assoc was implicitly merged into this Session prior to SQLAlchemy 2.0. - if object_session(self): - object_session(self).add(output_assoc) + ensure_object_added_to_session(output_assoc, object_in_session=self) output_assoc.dataset_collection = output_object output_assoc.output_name = output_name self.output_dataset_collections.append(output_assoc) diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py index 53fe0c99bee..27dbaa6ffa3 100644 --- a/lib/galaxy/model/store/__init__.py +++ b/lib/galaxy/model/store/__init__.py @@ -40,10 +40,7 @@ from rocrate.model.computationalworkflow import ( ) from rocrate.rocrate import ROCrate from sqlalchemy import select -from sqlalchemy.orm import ( - joinedload, - object_session, -) +from sqlalchemy.orm import joinedload from sqlalchemy.orm.scoping import scoped_session from sqlalchemy.sql import expression from typing_extensions import Protocol @@ -60,6 +57,7 @@ from galaxy.files import ( ) from galaxy.files.uris import stream_url_to_file from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.model.mapping import GalaxyModelMapping from galaxy.model.metadata import MetadataCollection from galaxy.model.orm.util import ( @@ -1027,9 +1025,7 @@ class ModelImportStore(metaclass=abc.ABCMeta): imported_invocation = model.WorkflowInvocation() imported_invocation.user = self.user imported_invocation.history = history - # Safeguard: imported_invocation was implicitly merged into this Session prior to SQLAlchemy 2.0. - if history and object_session(history): - object_session(history).add(imported_invocation) + ensure_object_added_to_session(imported_invocation, object_in_session=history) workflow_key = invocation_attrs["workflow"] if workflow_key not in object_import_tracker.workflows_by_key: raise Exception(f"Failed to find key {workflow_key} in {object_import_tracker.workflows_by_key.keys()}") @@ -1051,8 +1047,7 @@ class ModelImportStore(metaclass=abc.ABCMeta): for step_attrs in invocation_attrs["steps"]: imported_invocation_step = model.WorkflowInvocationStep() imported_invocation_step.workflow_invocation = imported_invocation - # Safeguard: imported_invocation_step was implicitly merged into this Session prior to SQLAlchemy 2.0. - self.sa_session.add(imported_invocation_step) + ensure_object_added_to_session(imported_invocation, session=self.sa_session) attach_workflow_step(imported_invocation_step, step_attrs) restore_times(imported_invocation_step, step_attrs) imported_invocation_step.action = step_attrs["action"] diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py index d9766abf3fe..59c3adda8a2 100644 --- a/lib/galaxy/webapps/base/webapp.py +++ b/lib/galaxy/webapps/base/webapp.py @@ -24,7 +24,6 @@ from sqlalchemy import ( select, true, ) -from sqlalchemy.orm import object_session from sqlalchemy.orm.exc import NoResultFound from galaxy import util @@ -39,6 +38,7 @@ from galaxy.managers import context from galaxy.managers.session import GalaxySessionManager from galaxy.managers.users import UserManager from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.structured_app import ( BasicSharedApp, MinimalApp, @@ -1120,9 +1120,7 @@ def create_new_session(trans, prev_galaxy_session=None, user_for_new_session=Non if user_for_new_session: # The new session should be associated with the user galaxy_session.user = user_for_new_session - # Safeguard: galaxy_session was implicitly merged into this Session prior to SQLAlchemy 2.0. - if user_for_new_session and object_session(user_for_new_session): - object_session(user_for_new_session).add(galaxy_session) + ensure_object_added_to_session(galaxy_session, object_in_session=user_for_new_session) return galaxy_session diff --git a/lib/galaxy/workflow/extract.py b/lib/galaxy/workflow/extract.py index 064b15f7efd..ad196a82d28 100644 --- a/lib/galaxy/workflow/extract.py +++ b/lib/galaxy/workflow/extract.py @@ -9,6 +9,7 @@ from galaxy import ( model, ) from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.tool_util.parser import ToolOutputCollectionPart from galaxy.tools.parameters.basic import ( DataCollectionToolParameter, @@ -71,8 +72,7 @@ def extract_workflow( workflow.stored_workflow = stored stored.latest_workflow = workflow trans.sa_session.add(stored) - # Safeguard: workflow was implicitly merged into this Session prior to SQLAlchemy 2.0. - trans.sa_session.add(workflow) + ensure_object_added_to_session(workflow, session=trans.sa_session) with transaction(trans.sa_session): trans.sa_session.commit() return stored diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index 9a2240b2dd6..cf6d0ebcce3 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -18,7 +18,6 @@ from typing import ( ) from cwl_utils.expression import do_eval -from sqlalchemy.orm import object_session from typing_extensions import TypedDict from galaxy import ( @@ -36,6 +35,7 @@ from galaxy.model import ( WorkflowStep, WorkflowStepConnection, ) +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.model.dataset_collections import matching from galaxy.schema.invocation import ( CancelReason, @@ -645,9 +645,7 @@ class SubWorkflowModule(WorkflowModule): def save_to_step(self, step, **kwd): step.type = self.type step.subworkflow = self.subworkflow - # Safeguard: step was implicitly merged into this Session prior to SQLAlchemy 2.0. - if self.subworkflow and object_session(self.subworkflow): - object_session(self.subworkflow).add(step) + ensure_object_added_to_session(step, object_in_session=self.subworkflow) def get_name(self): if hasattr(self.subworkflow, "name"): diff --git a/lib/galaxy/workflow/run.py b/lib/galaxy/workflow/run.py index e50962b8a27..de89a6a4032 100644 --- a/lib/galaxy/workflow/run.py +++ b/lib/galaxy/workflow/run.py @@ -10,7 +10,6 @@ from typing import ( Union, ) -from sqlalchemy.orm import object_session from typing_extensions import Protocol from galaxy import model @@ -20,6 +19,7 @@ from galaxy.model import ( WorkflowInvocationStep, ) from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.schema.invocation import ( CancelReason, FailureReason, @@ -226,9 +226,7 @@ class WorkflowInvoker: workflow_invocation_step = WorkflowInvocationStep() assert workflow_invocation_step workflow_invocation_step.workflow_invocation = workflow_invocation - # Safeguard: workflow_invocation_step was implicitly merged into this Session prior to SQLAlchemy 2.0. - if workflow_invocation and object_session(workflow_invocation): - object_session(workflow_invocation).add(workflow_invocation_step) + ensure_object_added_to_session(workflow_invocation_step, object_in_session=workflow_invocation) workflow_invocation_step.workflow_step = step workflow_invocation_step.state = "new" diff --git a/lib/galaxy/workflow/run_request.py b/lib/galaxy/workflow/run_request.py index b6ce3070e54..2ba9c4e8259 100644 --- a/lib/galaxy/workflow/run_request.py +++ b/lib/galaxy/workflow/run_request.py @@ -9,8 +9,6 @@ from typing import ( TYPE_CHECKING, ) -from sqlalchemy.orm import object_session - from galaxy import exceptions from galaxy.model import ( EffectiveOutput, @@ -24,6 +22,7 @@ from galaxy.model import ( WorkflowRequestStepState, ) from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy.tools.parameters.meta import expand_workflow_inputs from galaxy.workflow.resources import get_resource_mapper_function @@ -488,9 +487,7 @@ def workflow_run_config_to_request( workflow_invocation = WorkflowInvocation() workflow_invocation.uuid = uuid.uuid1() workflow_invocation.history = run_config.target_history - # Safeguard: workflow_invocation was implicitly merged into this Session prior to SQLAlchemy 2.0. - if run_config.target_history and object_session(run_config.target_history): - object_session(run_config.target_history).add(workflow_invocation) + ensure_object_added_to_session(workflow_invocation, object_in_session=run_config.target_history) def add_parameter(name: str, value: str, type: WorkflowRequestInputParameter.types) -> None: parameter = WorkflowRequestInputParameter( diff --git a/test/integration/test_job_files.py b/test/integration/test_job_files.py index f9f6cfaae54..8d0d4422c73 100644 --- a/test/integration/test_job_files.py +++ b/test/integration/test_job_files.py @@ -20,10 +20,10 @@ import tempfile import requests from sqlalchemy import select -from sqlalchemy.orm import object_session from galaxy import model from galaxy.model.base import transaction +from galaxy.model.database_utils import ensure_object_added_to_session from galaxy_test.base import api_asserts from galaxy_test.base.populators import DatasetPopulator from galaxy_test.driver import integration_util @@ -139,8 +139,7 @@ class TestJobFilesIntegration(integration_util.IntegrationTestCase): sa_session.commit() job = model.Job() job.history = history - # Safeguard: job was implicitly merged into this Session prior to SQLAlchemy 2.0. - object_session(history).add(job) + ensure_object_added_to_session(job, object_in_session=history) job.user = user job.handler = "unknown-handler" job.state = state