diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd
index 461600fa68b5..6ad79a7549a2 100644
--- a/lib/galaxy/tool_util/xsd/galaxy.xsd
+++ b/lib/galaxy/tool_util/xsd/galaxy.xsd
@@ -4039,6 +4039,16 @@ of "type" specified for this expression block.
+
+
+ Select a request method, defaults to GET if unspecified
+
+
+
+
+
+
+
Determine options from data hosted at specified URL.
+
+
+ Set the request method to use for options provided using from_url.
+
+
Deprecated.
@@ -4446,10 +4461,12 @@ used to generate dynamic options.
-
-
-
-
+
+
+
+
+
+
Documentation for file
@@ -4458,6 +4475,20 @@ used to generate dynamic options.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Optional[str]:
+ if maybe_string is not None:
+ if maybe_string.text:
+ return maybe_string.text.strip()
+ return None
+
+
+def parse_from_url_options(elem: Element) -> Optional[FromUrlOptions]:
+ from_url = elem.get("from_url")
+ if from_url:
+ request_method = cast(Literal["GET", "POST"], elem.get("request_method", "GET"))
+ assert request_method in get_args(REQUEST_METHODS)
+ request_headers = strip_or_none(elem.find("request_headers"))
+ request_body = strip_or_none(elem.find("request_body"))
+ postprocess_expression = strip_or_none(elem.find("postprocess_expression"))
+ return FromUrlOptions(
+ from_url,
+ request_method=request_method,
+ request_headers=request_headers,
+ request_body=request_body,
+ postprocess_expression=postprocess_expression,
+ )
+ return None
+
+
+def template_or_none(template: Optional[str], context: Dict[str, Any]) -> Optional[str]:
+ if template:
+ return fill_template(template, context=context)
+ return None
+
+
def _get_ref_data(other_values, ref_name):
"""
get the list of data sets from ref_name
diff --git a/lib/galaxy/work/context.py b/lib/galaxy/work/context.py
index a5bb476e0d19..8e4fc74afc21 100644
--- a/lib/galaxy/work/context.py
+++ b/lib/galaxy/work/context.py
@@ -4,6 +4,7 @@
Dict,
List,
Optional,
+ Tuple,
)
from typing_extensions import Literal
@@ -44,15 +45,15 @@ def __init__(
self.__user_current_roles: Optional[List[Role]] = None
self.__history = history
self._url_builder = url_builder
- self._short_term_cache: Dict[str, Any] = {}
+ self._short_term_cache: Dict[Tuple[str, ...], Any] = {}
self.workflow_building_mode = workflow_building_mode
self.galaxy_session = galaxy_session
- def set_cache_value(self, key: str, value: Any):
- self._short_term_cache[key] = value
+ def set_cache_value(self, args: Tuple[str, ...], value: Any):
+ self._short_term_cache[args] = value
- def get_cache_value(self, key: str, default: Any = None) -> Any:
- return self._short_term_cache.get(key, default)
+ def get_cache_value(self, args: Tuple[str, ...], default: Any = None) -> Any:
+ return self._short_term_cache.get(args, default)
@property
def app(self):
diff --git a/test/functional/tools/select_from_url.xml b/test/functional/tools/select_from_url.xml
index 260b239dc908..60a712e74631 100644
--- a/test/functional/tools/select_from_url.xml
+++ b/test/functional/tools/select_from_url.xml
@@ -2,7 +2,8 @@
'$param_value' &&
echo '$url_param_value_postprocessed' > '$param_value_postprocessed' &&
-echo '$invalid_url_param_value_postprocessed' > '$invalid_param_value_postprocessed'
+echo '$invalid_url_param_value_postprocessed' > '$invalid_param_value_postprocessed' &&
+echo '$url_param_value_header_and_body' > '$param_value_header_and_body'
]]>
@@ -33,17 +34,34 @@ echo '$invalid_url_param_value_postprocessed' > '$invalid_param_value_postproces
}]]>
+
+
+
+
+ {"x-api-key": "${__user__.extra_preferences.fake_api_key if $__user__ else "anon"}"}
+
+
+ {"name": "value"}
+
+
+ [header, header])
+ }]]>
+
+
+
+
+
diff --git a/test/unit/app/tools/test_dynamic_options.py b/test/unit/app/tools/test_dynamic_options.py
new file mode 100644
index 000000000000..38626d65b991
--- /dev/null
+++ b/test/unit/app/tools/test_dynamic_options.py
@@ -0,0 +1,57 @@
+from galaxy.app_unittest_utils.galaxy_mock import MockApp
+from galaxy.tools.parameters.dynamic_options import DynamicOptions
+from galaxy.util import XML
+from galaxy.util.bunch import Bunch
+from galaxy.work.context import WorkRequestContext
+
+
+def get_from_url_option():
+ return DynamicOptions(
+ XML(
+ """
+
+
+ {"x-api-key": "${__user__.extra_preferences.resource_api_key if $__user__ else "anon"}"}
+
+
+ {"some_key": "some_value"}
+
+ [v.chrom, v.len])
+ } else {
+ return [["The fallback value", "default"]]
+ }
+ }]]>
+
+"""
+ ),
+ Bunch(),
+ )
+
+
+def test_dynamic_option_parsing():
+ from_url_option = get_from_url_option()
+ assert from_url_option.from_url_options
+ assert from_url_option.from_url_options.from_url == "https://usegalaxy.org/api/genomes/dm6"
+
+
+def test_dynamic_option_cache():
+ app = MockApp()
+ trans = WorkRequestContext(app=app)
+ from_url_option = get_from_url_option()
+ options = from_url_option.from_url_options
+ assert options
+ args = (options.from_url, options.request_method, options.request_body, '{"x-api-key": "anon"}')
+ trans.set_cache_value(
+ args,
+ {
+ "id": "dm6",
+ "reference": True,
+ "chrom_info": [{"chrom": "chr2L", "len": 23513712}],
+ "prev_chroms": False,
+ "next_chroms": False,
+ "start_index": 0,
+ },
+ )
+ assert from_url_option.get_options(trans, {}) == [["chr2L", "23513712", False]]