From c3a2fe4d737a37a6a3db379382576c7a87117500 Mon Sep 17 00:00:00 2001 From: John Davis Date: Thu, 10 Aug 2023 23:44:01 -0400 Subject: [PATCH 1/5] Patch MockContext for SA 2.0 compatibility --- lib/galaxy/app_unittest_utils/tools_support.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/galaxy/app_unittest_utils/tools_support.py b/lib/galaxy/app_unittest_utils/tools_support.py index 38d491d5d7a3..e6566c4798d4 100644 --- a/lib/galaxy/app_unittest_utils/tools_support.py +++ b/lib/galaxy/app_unittest_utils/tools_support.py @@ -133,6 +133,9 @@ def expunge_all(self): def query(self, clazz): return MockQuery(self.model_objects.get(clazz)) + def get(self, clazz, id): + return self.query(clazz).get(id) + def flush(self): self.flushed = True From 33791744062f00f085c47d5d8a240a59c91dc974 Mon Sep 17 00:00:00 2001 From: John Davis Date: Fri, 11 Aug 2023 10:36:43 -0400 Subject: [PATCH 2/5] Resuse MockQuery and MockContext in other unit tests --- .../app_unittest_utils/tools_support.py | 3 ++ test/unit/app/jobs/test_job_wrapper.py | 38 ++----------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/lib/galaxy/app_unittest_utils/tools_support.py b/lib/galaxy/app_unittest_utils/tools_support.py index e6566c4798d4..77c759499d75 100644 --- a/lib/galaxy/app_unittest_utils/tools_support.py +++ b/lib/galaxy/app_unittest_utils/tools_support.py @@ -142,6 +142,9 @@ def flush(self): def add(self, object): self.created_objects.append(object) + def commit(self): + pass + class MockQuery: def __init__(self, class_objects): diff --git a/test/unit/app/jobs/test_job_wrapper.py b/test/unit/app/jobs/test_job_wrapper.py index 697bd5510272..43d958bc5400 100644 --- a/test/unit/app/jobs/test_job_wrapper.py +++ b/test/unit/app/jobs/test_job_wrapper.py @@ -7,7 +7,10 @@ Type, ) -from galaxy.app_unittest_utils.tools_support import UsesApp +from galaxy.app_unittest_utils.tools_support import ( + MockContext, + UsesApp, +) from galaxy.jobs import ( JobWrapper, TaskWrapper, @@ -134,39 +137,6 @@ def url_to_destination(self): pass -class MockContext: - def __init__(self, model_objects): - self.expunged_all = False - self.model_objects = model_objects - self.created_objects = [] - - def expunge_all(self): - self.expunged_all = True - - def query(self, clazz): - return MockQuery(self.model_objects.get(clazz)) - - def flush(self): - pass - - def commit(self): - pass - - def add(self, object): - self.created_objects.append(object) - - -class MockQuery: - def __init__(self, class_objects): - self.class_objects = class_objects - - def filter_by(self, **kwds): - return Bunch(first=lambda: None) - - def get(self, id): - return self.class_objects.get(id, None) - - class MockTool: def __init__(self, app): self.version_string_cmd = TEST_VERSION_COMMAND From 9540ee3bf23ca7a507cc1619d71d1af30ac7055e Mon Sep 17 00:00:00 2001 From: John Davis Date: Thu, 10 Aug 2023 23:32:49 -0400 Subject: [PATCH 3/5] Patch SessionlessContext for SA 2.0 (get method) --- lib/galaxy/model/store/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py index 8be4bbe25c6a..b70b6740bba8 100644 --- a/lib/galaxy/model/store/__init__.py +++ b/lib/galaxy/model/store/__init__.py @@ -218,6 +218,9 @@ def filter_by(*args, **kwargs): return Bunch(find=find, get=find, filter_by=filter_by) + def get(self, model_class: Type, primary_key: Any): # patch for SQLAlchemy 2.0 compatibility + return self.query(model_class).get(primary_key) + def replace_metadata_file( metadata: Dict[str, Any], From 00bce2e3184c517e40f7dbdc3b34dd6ca2455185 Mon Sep 17 00:00:00 2001 From: John Davis Date: Fri, 11 Aug 2023 17:43:37 -0400 Subject: [PATCH 4/5] Simplify typing of SessionlessContext --- lib/galaxy/managers/history_contents.py | 2 +- lib/galaxy/model/__init__.py | 2 +- lib/galaxy/model/store/__init__.py | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/galaxy/managers/history_contents.py b/lib/galaxy/managers/history_contents.py index cbb0f9fa3051..5c8795270e02 100644 --- a/lib/galaxy/managers/history_contents.py +++ b/lib/galaxy/managers/history_contents.py @@ -437,7 +437,7 @@ def _contained_id_map(self, id_list): query = ( self._session() .query(component_class) - .filter(component_class.id.in_(id_list)) + .filter(component_class.id.in_(id_list)) # type: ignore[attr-defined] .options(undefer(component_class._metadata)) .options(joinedload(component_class.dataset).joinedload(model.Dataset.actions)) .options(joinedload(component_class.tags)) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 7ae306105b4b..2b931668a18d 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -4277,7 +4277,7 @@ def datatype_for_extension(extension, datatypes_registry=None) -> "Data": return ret -class DatasetInstance(UsesCreateAndUpdateTime, _HasTable): +class DatasetInstance(RepresentById, UsesCreateAndUpdateTime, _HasTable): """A base class for all 'dataset instances', HDAs, LDAs, etc""" states = Dataset.states diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py index b70b6740bba8..ea10a0bca4d7 100644 --- a/lib/galaxy/model/store/__init__.py +++ b/lib/galaxy/model/store/__init__.py @@ -205,10 +205,10 @@ def commit(self) -> None: def flush(self) -> None: pass - def add(self, obj: Union[model.DatasetInstance, model.RepresentById]) -> None: + def add(self, obj: model.RepresentById) -> None: self.objects[obj.__class__][obj.id] = obj - def query(self, model_class: Type) -> Bunch: + def query(self, model_class: model.RepresentById) -> Bunch: def find(obj_id): return self.objects.get(model_class, {}).get(obj_id) or None @@ -218,7 +218,7 @@ def filter_by(*args, **kwargs): return Bunch(find=find, get=find, filter_by=filter_by) - def get(self, model_class: Type, primary_key: Any): # patch for SQLAlchemy 2.0 compatibility + def get(self, model_class: model.RepresentById, primary_key: Any): # patch for SQLAlchemy 2.0 compatibility return self.query(model_class).get(primary_key) @@ -894,7 +894,7 @@ def materialize_elements(dc): def _attach_raw_id_if_editing( self, - obj: Union[model.DatasetInstance, model.RepresentById], + obj: model.RepresentById, attrs: Dict[str, Any], ) -> None: if self.sessionless and "id" in attrs and self.import_options.allow_edit: @@ -1272,7 +1272,7 @@ def _import_implicit_collection_jobs(self, object_import_tracker: "ObjectImportT self._session_add(icj) - def _session_add(self, obj: Union[model.DatasetInstance, model.RepresentById]) -> None: + def _session_add(self, obj: model.RepresentById) -> None: self.sa_session.add(obj) def _flush(self) -> None: @@ -1961,7 +1961,7 @@ def add(src, dest): def exported_key( self, - obj: Union[model.DatasetInstance, model.RepresentById], + obj: model.RepresentById, ) -> Union[str, int]: return self.serialization_options.get_identifier(self.security, obj) From d61a9daa5f521ed6da3b1d555668021bf2b135dc Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 15 Aug 2023 10:22:36 -0400 Subject: [PATCH 5/5] Add session attr to Bunch to facilitate app.model.session This Bunch object already has `context`; however we access the session using both attrs. --- lib/galaxy/tools/remote_tool_eval.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/tools/remote_tool_eval.py b/lib/galaxy/tools/remote_tool_eval.py index cc3f668b7657..e69ce53899af 100644 --- a/lib/galaxy/tools/remote_tool_eval.py +++ b/lib/galaxy/tools/remote_tool_eval.py @@ -60,7 +60,8 @@ def __init__( tool_data_table_manager: ToolDataTableManager, file_sources: ConfiguredFileSources, ): - self.model = Bunch(context=sa_session) + # For backward compatibility we need both context and session attributes that point to sa_session. + self.model = Bunch(context=sa_session, session=sa_session) self.config = tool_app_config self.datatypes_registry = datatypes_registry self.object_store = object_store