diff --git a/client/package.json b/client/package.json index 3b98022b6b3..e2f369d92f9 100644 --- a/client/package.json +++ b/client/package.json @@ -57,6 +57,7 @@ "jspdf": "^2.5.1", "linkify-html": "^3.0.5", "linkifyjs": "^3.0.5", + "localforage": "^1.10.0", "markdown-it": "^12.3.2", "markdown-it-regexp": "^0.4.0", "moment": "2.29.1", @@ -95,8 +96,7 @@ "vueisotope": "^3.1.2", "vuex": "^3.6.2", "vuex-cache": "^3.4.0", - "vuex-persist": "^3.1.3", - "vuex-persistedstate": "^4.1.0", + "vuex-persist": "2.3", "xml-beautifier": "^0.5.0" }, "scripts": { diff --git a/client/src/components/HistoryExport/ToLink.vue b/client/src/components/HistoryExport/ToLink.vue index e468c02fc76..041f95effdd 100644 --- a/client/src/components/HistoryExport/ToLink.vue +++ b/client/src/components/HistoryExport/ToLink.vue @@ -17,7 +17,11 @@
Link for download ready - . Use this link to download the archive or import it on another Galaxy server. +

Use this link to download the archive or import it on another Galaxy server.

+ History archives are removed at regular intervals. For permanent storage download the archive, export + to a remote file or import the archive on another Galaxy server. +

An out of date export is ready .

diff --git a/client/src/components/Panels/ToolBox.vue b/client/src/components/Panels/ToolBox.vue index 3af9756d9b7..5abc1cd1701 100644 --- a/client/src/components/Panels/ToolBox.vue +++ b/client/src/components/Panels/ToolBox.vue @@ -166,8 +166,9 @@ export default { } else if (tool.form_style === "regular") { evt.preventDefault(); const Galaxy = getGalaxyInstance(); + // encode spaces in tool.id Galaxy.router.push("/", { - tool_id: tool.id, + tool_id: tool.id.replace(/ /g, "%20"), version: tool.version, }); } diff --git a/client/src/store/index.js b/client/src/store/index.js index b6b06ed2963..734d60ffb22 100644 --- a/client/src/store/index.js +++ b/client/src/store/index.js @@ -5,7 +5,8 @@ import Vue from "vue"; import Vuex from "vuex"; import createCache from "vuex-cache"; -import createPersistedState from "vuex-persistedstate"; +import VuexPersistence from "vuex-persist"; +import localForage from "localforage"; import config from "config"; @@ -35,19 +36,28 @@ import { syncVuextoGalaxy } from "./syncVuextoGalaxy"; Vue.use(Vuex); -const panelsState = createPersistedState({ - paths: ["panels"], +const galaxyStorage = localForage.createInstance({}); +galaxyStorage.config({ + driver: [localForage.INDEXEDDB, localForage.LOCALSTORAGE], + name: "galaxyIndexedDB", + version: 1.0, + storeName: "galaxyStore", +}); + +const panelsPersistence = new VuexPersistence({ + storage: galaxyStorage, + asyncStorage: true, + modules: ["panels"], }); export function createStore() { const storeConfig = { - plugins: [createCache(), panelsState], + plugins: [createCache(), panelsPersistence.plugin], modules: { user: userStore, config: configStore, betaHistory: betaHistoryStore, panels: panelStore, - // TODO: please namespace all store modules gridSearch: gridSearchStore, histories: historyStore, diff --git a/client/src/ui/search-input.js b/client/src/ui/search-input.js index 21c36f4e7dd..06acd5ce212 100644 --- a/client/src/ui/search-input.js +++ b/client/src/ui/search-input.js @@ -152,6 +152,18 @@ function searchInput(parentNode, options) { .popover("show"); }); } + // Hack to hide the advanced search popover when clicking outside + $("body").on("click", function (e) { + $('[data-toggle="advSearchPopover"]').each(function () { + if ( + !$(this).is(e.target) && + $(this).has(e.target).length === 0 && + $(".popover").has(e.target).length === 0 + ) { + $(this).popover("hide"); + } + }); + }); // .................................................................... loadingIndicator rendering // a button for clearing the search bar, placed on the right hand side diff --git a/client/yarn.lock b/client/yarn.lock index 5c98a827544..f5412e2ff8e 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -4625,10 +4625,15 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flatted@^3.0.5, flatted@^3.1.0, flatted@^3.2.4: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +flatted@^3.1.0, flatted@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== flush-promises@^1.0.2: version "1.0.2" @@ -5216,6 +5221,11 @@ imask@^6.4.0: resolved "https://registry.yarnpkg.com/imask/-/imask-6.4.0.tgz#76e48e6bbf5306f7de058f8a1b90fd2282d446bc" integrity sha512-iXXgSQA6TJX/RSKivKoTYYoCc4ZmVseMcoDIxMrlW1JPpc8LU9FtCp3f80vg1eUQvmVfEQbh+vybFVDRt2o9TQ== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= + immutable@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" @@ -6556,6 +6566,13 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + dependencies: + immediate "~3.0.5" + liftoff@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" @@ -6631,6 +6648,13 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" +localforage@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" + integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== + dependencies: + lie "3.1.1" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -6718,7 +6742,7 @@ lodash.uniqby@4.5.0: lodash._baseiteratee "~4.7.0" lodash._baseuniq "~4.6.0" -lodash@^4.13.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.13.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7207,12 +7231,17 @@ object-hash@^2.2.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-inspect@^1.11.0, object-inspect@^1.9.0: +object-inspect@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + +object-inspect@^1.9.0: version "1.12.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== -object-is@^1.0.1, object-is@^1.1.4: +object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -7220,6 +7249,14 @@ object-is@^1.0.1, object-is@^1.1.4: call-bind "^1.0.2" define-properties "^1.1.3" +object-is@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.4.tgz#63d6c83c00a43f4cbc9434eb9757c8a5b8565068" + integrity sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -8667,11 +8704,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shvl@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/shvl/-/shvl-2.0.3.tgz#eb4bd37644f5684bba1fc52c3010c96fb5e6afd1" - integrity sha512-V7C6S9Hlol6SzOJPnQ7qzOVEWUQImt3BNmmzh40wObhla3XOYMe4gGiYzLrJd5TFa+cI2f9LKIRJTTKZSTbWgw== - side-channel@^1.0.3, side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -9907,21 +9939,13 @@ vuex-cache@^3.4.0: resolved "https://registry.yarnpkg.com/vuex-cache/-/vuex-cache-3.4.0.tgz#0aec66b7abb370b1a089f678681af8efe5a9289b" integrity sha512-C0HJvVTEdjn8gq0EXemcJCBgAyPLnms8VGz/kMakrpaF6XNwkZY5KvySkdBJSY6rp0eTdWMoHPVU2Oq+dK7WEQ== -vuex-persist@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/vuex-persist/-/vuex-persist-3.1.3.tgz#518c722a2ca3026bcee5732f99d24f75cee0f3b6" - integrity sha512-QWOpP4SxmJDC5Y1+0+Yl/F4n7z27syd1St/oP+IYCGe0X0GFio0Zan6kngZFufdIhJm+5dFGDo3VG5kdkCGeRQ== +vuex-persist@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vuex-persist/-/vuex-persist-2.3.0.tgz#f3d21b6d631078667d6834f2f74442ee332ac281" + integrity sha512-0QPZQYgQ72SbXkdwctXGFQJhlRiySP0z9wHDBTlyHvNy3CneKvgyJ7Lfob8NUiYbaurJepaC+JFynwshp59FGA== dependencies: - deepmerge "^4.2.2" - flatted "^3.0.5" - -vuex-persistedstate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-4.1.0.tgz#127165f85f5b4534fb3170a5d3a8be9811bd2a53" - integrity sha512-3SkEj4NqwM69ikJdFVw6gObeB0NHyspRYMYkR/EbhR0hbvAKyR5gksVhtAfY1UYuWUOCCA0QNGwv9pOwdj+XUQ== - dependencies: - deepmerge "^4.2.2" - shvl "^2.0.3" + flatted "^2.0.0" + lodash "^4.17.19" vuex@^3.6.2: version "3.6.2" diff --git a/lib/galaxy/jobs/runners/univa.py b/lib/galaxy/jobs/runners/univa.py index 5a3117c6456..c0d2ecb730c 100644 --- a/lib/galaxy/jobs/runners/univa.py +++ b/lib/galaxy/jobs/runners/univa.py @@ -32,6 +32,7 @@ import logging import re import signal import time +from math import inf from galaxy.jobs.runners.drmaa import DRMAAJobRunner from galaxy.util import ( @@ -587,8 +588,8 @@ def _parse_native_specs(job_id, native_spec): specification string passed to GE return time,mem (or None,None if nothing found) """ - tme = None - mem = None + tme = inf + mem = inf # parse time m = re.search(r"rt=([0-9:]+)[\s,]*", native_spec) if m is not None: diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 7a076b0397e..23ec3a031a4 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -7085,7 +7085,7 @@ class WorkflowStepConnection(Base, RepresentById): return self.input_step_input.name @property - def input_step(self): + def input_step(self) -> Optional[WorkflowStep]: return self.input_step_input and self.input_step_input.workflow_step @property diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py index 9f63050c9a6..f1fdf05591d 100644 --- a/lib/galaxy/model/store/__init__.py +++ b/lib/galaxy/model/store/__init__.py @@ -1470,7 +1470,7 @@ class DirectoryModelExportStore(ModelExportStore): datasets = query.all() for dataset in datasets: dataset.annotation = get_item_annotation_str(sa_session, history.user, dataset) - add_dataset = (not dataset.visible or not include_hidden) and (not dataset.deleted or include_deleted) + add_dataset = (dataset.visible or include_hidden) and (not dataset.deleted or include_deleted) if dataset.id in self.collection_datasets: add_dataset = True diff --git a/lib/galaxy/selenium/navigation.yml b/lib/galaxy/selenium/navigation.yml index ebc97f3e2b7..debfd06a3d9 100644 --- a/lib/galaxy/selenium/navigation.yml +++ b/lib/galaxy/selenium/navigation.yml @@ -526,6 +526,9 @@ workflow_run: subworkflow_step_icon: ".portlet-title-icon.fa-sitemap" run_workflow: "#run-workflow" validation_error: ".validation-error" + input_select_field: + type: xpath + selector: '//div[@data-label="${label}"]//span[@class="select2-chosen"]' workflow_editor: diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py index 69b00ff14d3..89e170899ab 100644 --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -9,6 +9,7 @@ from typing import ( Any, cast, Dict, + Iterable, List, Optional, Union, @@ -27,6 +28,7 @@ from galaxy.job_execution.actions.post import ActionBox from galaxy.model import ( PostJobAction, Workflow, + WorkflowStepConnection, ) from galaxy.model.dataset_collections import matching from galaxy.tool_util.parser.output_objects import ToolExpressionOutput @@ -817,7 +819,12 @@ class InputDataCollectionModule(InputModule): ] input_collection_type = TextToolParameter(None, collection_type_source) tag_source = dict( - name="tag", label="Tag filter", type="text", value=tag, help="Tags to automatically filter inputs" + name="tag", + label="Tag filter", + type="text", + optional="true", + value=tag, + help="Tags to automatically filter inputs", ) input_tag = TextToolParameter(None, tag_source) inputs = {} @@ -881,7 +888,7 @@ class InputParameterModule(WorkflowModule): name = "Input parameter" default_parameter_type = "text" default_optional = False - default_default_value = "" + default_default_value = None parameter_type = default_parameter_type optional = default_optional default_value = default_default_value @@ -1097,10 +1104,53 @@ class InputParameterModule(WorkflowModule): parameter_type_cond.cases = cases return {"parameter_definition": parameter_type_cond} - def get_runtime_inputs(self, connections=None, **kwds): + def restrict_options(self, connections: Iterable[WorkflowStepConnection], default_value): + try: + static_options = [] + # Retrieve possible runtime options for 'select' type inputs + for connection in connections: + # Well this isn't a great assumption... + module = connection.input_step.module # type: ignore[union-attr] + tool_inputs = module.tool.inputs # may not be set, but we're catching the Exception below. + + def callback(input, prefixed_name, context, **kwargs): + if prefixed_name == connection.input_name and hasattr(input, "get_options"): + static_options.append(input.get_options(self.trans, {})) + + visit_input_values(tool_inputs, module.state.inputs, callback) + + options = None + if static_options and len(static_options) == 1: + # If we are connected to a single option, just use it as is so order is preserved cleanly and such. + options = [ + {"label": o[0], "value": o[1], "selected": bool(default_value and o[1] == default_value)} + for o in static_options[0] + ] + elif static_options: + # Intersection based on values of multiple option connections. + intxn_vals = set.intersection(*({option[1] for option in options} for options in static_options)) + intxn_opts = {option for options in static_options for option in options if option[1] in intxn_vals} + d = defaultdict(set) # Collapse labels with same values + for label, value, _ in intxn_opts: + d[value].add(label) + options = [ + { + "label": ", ".join(label), + "value": value, + "selected": bool(default_value and value == default_value), + } + for value, label in d.items() + ] + + return options + except Exception: + log.debug("Failed to generate options for text parameter, falling back to free text.", exc_info=True) + + def get_runtime_inputs(self, connections: Optional[Iterable[WorkflowStepConnection]] = None, **kwds): parameter_def = self._parse_state_into_dict() parameter_type = parameter_def["parameter_type"] optional = parameter_def["optional"] + default_value = parameter_def.get("default", self.default_default_value) if parameter_type not in ["text", "boolean", "integer", "float", "color"]: raise ValueError("Invalid parameter type for workflow parameters encountered.") @@ -1113,41 +1163,12 @@ class InputParameterModule(WorkflowModule): # Really is just an attempt - tool module may not be available (small problem), get_options may really depend on other # values we are not setting, so this isn't great. Be sure to just fallback to text in this case. attemptRestrictOnConnections = is_text and parameter_def.get("restrictOnConnections") and connections - try: - if attemptRestrictOnConnections: - static_options = [] - # Retrieve possible runtime options for 'select' type inputs - for connection in connections: - # Well this isn't a great assumption... - module = connection.input_step.module - tool_inputs = module.tool.inputs # may not be set, but we're catching the Exception below. - - def callback(input, prefixed_name, context, **kwargs): - if prefixed_name == connection.input_name and hasattr(input, "get_options"): - static_options.append(input.get_options(self.trans, {})) - - visit_input_values(tool_inputs, module.state.inputs, callback) - - options = None - if static_options and len(static_options) == 1: - # If we are connected to a single option, just use it as is so order is preserved cleanly and such. - options = [{"label": o[0], "value": o[1]} for o in static_options[0]] - elif static_options: - # Intersection based on values of multiple option connections. - intxn_vals = set.intersection(*({option[1] for option in options} for options in static_options)) - intxn_opts = {option for options in static_options for option in options if option[1] in intxn_vals} - d = defaultdict(set) # Collapse labels with same values - for label, value, _ in intxn_opts: - d[value].add(label) - options = [ - {"label": ", ".join(label), "value": value, "selected": False} for value, label in d.items() - ] - - if options is not None: - parameter_kwds["options"] = options - restricted_inputs = True - except Exception: - log.debug("Failed to generate options for text parameter, falling back to free text.", exc_info=True) + if attemptRestrictOnConnections: + connections = cast(Iterable[WorkflowStepConnection], connections) + restricted_options = self.restrict_options(connections=connections, default_value=default_value) + if restricted_options is not None: + restricted_inputs = True + parameter_kwds["options"] = restricted_options def _parameter_def_list_to_options(parameter_value): options = [] @@ -1178,8 +1199,10 @@ class InputParameterModule(WorkflowModule): parameter_class = parameter_types[client_parameter_type] if optional: - default_value = parameter_def.get("default", self.default_default_value) - parameter_kwds["value"] = default_value + if client_parameter_type == "select": + parameter_kwds["selected"] = default_value + else: + parameter_kwds["value"] = default_value if parameter_type == "boolean": parameter_kwds["checked"] = default_value diff --git a/lib/galaxy_test/selenium/test_workflow_run.py b/lib/galaxy_test/selenium/test_workflow_run.py index 977cbbe5a24..208df75e14a 100644 --- a/lib/galaxy_test/selenium/test_workflow_run.py +++ b/lib/galaxy_test/selenium/test_workflow_run.py @@ -190,6 +190,34 @@ steps: content = self.dataset_populator.get_history_dataset_content(history_id, hid=7) self.assertEqual("10.0\n30.0\n20.0\n40.0\n", content) + @selenium_test + @managed_history + def test_execution_with_text_default_value_connected_to_restricted_select(self): + self.open_in_workflow_run( + """ +class: GalaxyWorkflow +inputs: + text_param: + optional: true + default: ex2 + restrictOnConnections: true + type: text +steps: + multi_select: + tool_id: multi_select + in: + select_ex: + source: text_param +""" + ) + element = self.components.workflow_run.input_select_field(label="text_param").wait_for_present() + assert element.text == "Ex2" + self.workflow_run_submit() + history_id = self.current_history_id() + self.workflow_populator.wait_for_history_workflows(history_id, expected_invocation_count=1) + content = self.dataset_populator.get_history_dataset_content(history_id, hid=1) + assert content == "ex2" + @selenium_test @managed_history def test_execution_with_rules(self): diff --git a/scripts/common_startup.sh b/scripts/common_startup.sh index a8b4c2f0a94..9912a908050 100755 --- a/scripts/common_startup.sh +++ b/scripts/common_startup.sh @@ -122,7 +122,6 @@ if [ $SET_VENV -eq 1 ] && [ $CREATE_VENV -eq 1 ]; then conda_activate fi virtualenv "$GALAXY_VIRTUAL_ENV" - setup_gravity_state_dir else # If $GALAXY_VIRTUAL_ENV does not exist, and there is no conda available, attempt to create it. if [ -z "$GALAXY_PYTHON" ]; then @@ -140,7 +139,6 @@ if [ $SET_VENV -eq 1 ] && [ $CREATE_VENV -eq 1 ]; then echo "existing environment before starting Galaxy." if command -v virtualenv >/dev/null; then virtualenv -p "$GALAXY_PYTHON" "$GALAXY_VIRTUAL_ENV" - setup_gravity_state_dir else vvers=16.7.9 vurl="https://files.pythonhosted.org/packages/source/v/virtualenv/virtualenv-${vvers}.tar.gz" @@ -167,10 +165,10 @@ urlretrieve('$vurl', '$vsrc')" tar zxf "$vsrc" -C "$vtmp" "$GALAXY_PYTHON" "$vtmp/virtualenv-$vvers/virtualenv.py" "$GALAXY_VIRTUAL_ENV" rm -rf "$vtmp" - setup_gravity_state_dir fi fi fi + setup_gravity_state_dir fi # activate virtualenv or conda env, sets $GALAXY_VIRTUAL_ENV and $GALAXY_CONDA_ENV diff --git a/test/unit/data/model/test_model_store.py b/test/unit/data/model/test_model_store.py index 0605e4b93fb..220ca73b7f0 100644 --- a/test/unit/data/model/test_model_store.py +++ b/test/unit/data/model/test_model_store.py @@ -44,6 +44,30 @@ def test_import_export_history_failed_job(): _assert_simple_cat_job_imported(imported_history, state="error") +def test_import_export_history_hidden_false_with_hidden_dataset(): + app = _mock_app() + + u, h, d1, d2, j = _setup_simple_cat_job(app) + d2.visible = False + app.model.session.flush() + + imported_history = _import_export_history(app, h, export_files="copy", include_hidden=False) + assert d1.dataset.get_size() == imported_history.datasets[0].get_size() + assert imported_history.datasets[1].get_size() == 0 + + +def test_import_export_history_hidden_true_with_hidden_dataset(): + app = _mock_app() + + u, h, d1, d2, j = _setup_simple_cat_job(app) + d2.visible = False + app.model.session.flush() + + imported_history = _import_export_history(app, h, export_files="copy", include_hidden=True) + assert d1.dataset.get_size() == imported_history.datasets[0].get_size() + assert d2.dataset.get_size() == imported_history.datasets[1].get_size() + + def test_import_export_bag_archive(): """Test a simple job import/export using a BagIt archive.""" dest_parent = mkdtemp() @@ -488,13 +512,13 @@ def _setup_simple_cat_job(app, state="ok"): return u, h, d1, d2, j -def _import_export_history(app, h, dest_export=None, export_files=None): +def _import_export_history(app, h, dest_export=None, export_files=None, include_hidden=False): if dest_export is None: dest_parent = mkdtemp() dest_export = os.path.join(dest_parent, "moo.tgz") with store.TarModelExportStore(dest_export, app=app, export_files=export_files) as export_store: - export_store.export_history(h) + export_store.export_history(h, include_hidden=include_hidden) imported_history = import_archive(dest_export, app, h.user) assert imported_history