Commit ee46a52c authored by Sveinung Gundersen's avatar Sveinung Gundersen Committed by Cage, Gregory
Browse files

Merge 'Using label instead of name to identify entrypoint' into branch

parent d3170b9f
Loading
Loading
Loading
Loading
+63 −3
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@ import os
import re
import uuid
from typing import (
    Any,
    cast,
    Dict,
    Iterable,
    List,
    Optional,
@@ -60,6 +62,8 @@ log = logging.getLogger(__name__)
def inject_validates(inject):
    if inject == "api_key":
        return True
    elif inject == "entry_point_path_for_label":
        return True
    p = re.compile("^oidc_(id|access|refresh)_token_(.*)$")
    match = p.match(inject)
    return match is not None
@@ -229,10 +233,13 @@ class XmlToolSource(ToolSource):
            template = environment_variable_el.text
            inject = environment_variable_el.get("inject")
            if inject:
                assert not template, "Cannot specify inject and environment variable template."
                assert inject_validates(inject)
            if template:
                assert not inject, "Cannot specify inject and environment variable template."
            if inject == "entry_point_path_for_label":
                assert (
                    template
                ), 'Environment variable value must contain entry point label when inject="entry_point_path_for_label".'
            else:
                assert not (template and inject), "Cannot specify inject and environment variable template."
            definition = {
                "name": environment_variable_el.get("name"),
                "template": template,
@@ -303,6 +310,9 @@ class XmlToolSource(ToolSource):
            name = ep_el.get("name", None)
            if name:
                name = name.strip()
            label = ep_el.get("label", None)
            if label:
                label = label.strip()
            requires_domain = string_as_bool(ep_el.attrib.get("requires_domain", False))
            protocol = ep_el.attrib.get("protocol", "http")
            if protocol:
@@ -1277,6 +1287,56 @@ class XmlInputSource(InputSource):
            sources.append((value, case_page_source))
        return sources

    def parse_default(self) -> Optional[Dict[str, Any]]:
        def file_default_from_elem(elem):
            # TODO: hashes, created_from_basename, etc...
            return {"class": "File", "location": elem.get("location")}

        def read_elements(collection_elem):
            element_dicts = []
            elements = collection_elem.findall("element")
            for element in elements:
                identifier = element.get("name")
                subcollection_elem = element.find("collection")
                if subcollection_elem:
                    collection_type = subcollection_elem.get("collection_type")
                    element_dicts.append(
                        {
                            "class": "Collection",
                            "identifier": identifier,
                            "collection_type": collection_type,
                            "elements": read_elements(subcollection_elem),
                        }
                    )
                else:
                    element_dict = file_default_from_elem(element)
                    element_dict["identifier"] = identifier
                    element_dicts.append(element_dict)
            return element_dicts

        elem = self.input_elem
        element_type = self.input_elem.get("type")
        if element_type == "data":
            default_elem = elem.find("default")
            if default_elem is not None:
                return file_default_from_elem(default_elem)
            else:
                return None
        else:
            default_elem = elem.find("default")
            if default_elem is not None:
                default_elem = elem.find("default")
                collection_type = default_elem.get("collection_type")
                name = default_elem.get("name", elem.get("name"))
                return {
                    "class": "Collection",
                    "name": name,
                    "collection_type": collection_type,
                    "elements": read_elements(default_elem),
                }
            else:
                return None


class ParallelismInfo:
    """
+143 −11
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ to provide access to graphical tools in real-time.

```xml
<entry_points>
  <entry_point name="Example name">
  <entry_point name="Example name" label="example">
    <port>80</port>
    <url>landing/${template_enabled}/index.html</url>
  </entry_point>
@@ -385,12 +385,43 @@ to provide access to graphical tools in real-time.
    </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required">
          <xs:annotation>
            <xs:documentation xml:lang="en">This value defines the name of the entry point.</xs:documentation>
            <xs:documentation xml:lang="en">The name of the entry point.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="requires_domain" type="PermissiveBoolean" default="false">
        <xs:attribute name="label" type="xs:string" use="optional">
          <xs:annotation>
            <xs:documentation xml:lang="en">This value declares if domain-based proxying is required. Default is False. Currently only works when True.</xs:documentation>
            <xs:documentation xml:lang="en">A unique label to identify the entry point. Used by interactive client tools to connect.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="requires_domain" type="PermissiveBoolean" default="true">
          <xs:annotation>
            <xs:documentation xml:lang="en">Whether domain-based proxying is required for the entry point. Default is True.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="requires_path_in_url" type="PermissiveBoolean" default="false">
          <xs:annotation>
            <xs:documentation xml:lang="en"><![CDATA[
Whether the InteractiveTool proxy will add the entry point path to the URL provided to the interactive tool. Only
relevant when path-based proxying is configured (``requires_domain=False``). A value of False implies that the web service
for the interactive tool fully operates with relative links. A value of True implies that the unique entry point path,
which is autogenerated each run, must be somehow provided to the web service. This can be done by injecting the path
into an environment variable by setting the attribute ``inject="entry_point_path_for_label"`` in the tool XML.
Alternatively, the attribute ``requires_path_in_header_named`` can be set to provide the path in the specified HTTP header.
The entry point path should in any case be used to configure the web service in the interactive tool to serve the content
from the provided URL path. Default value of ``requires_path_in_url`` is False.
]]>
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="requires_path_in_header_named" type="xs:string" default="">
          <xs:annotation>
            <xs:documentation xml:lang="en"><![CDATA[
Whether the InteractiveTool proxy will add the entry point path to an HTTP header. An empty string as value (default) means
that the path will not be provided in an HTTP header. Any other string value will define the name of the HTTP header
where the path will be injected by the proxy. See the documentation of ``requires_path_in_url`` for more information.
Default value of ``requires_path_in_header_named`` is False.
]]>
            </xs:documentation>
          </xs:annotation>
        </xs:attribute>
  </xs:complexType>
@@ -1577,6 +1608,11 @@ non-optional composite inputs must be specified as part of the ``param``.
        <xs:documentation xml:lang="en">Type of collection to create.</xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="name" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">The identifier of the collection. Default is ``"Unnamed Collection"``</xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="tags" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">Comma separated list of tags to apply to the dataset (only works for elements of collections - e.g. ``element`` XML tags).</xs:documentation>
@@ -3248,6 +3284,19 @@ value of "V1".
<param name="xlab" type="text" value="V1" label="Label for x axis" />
```

Unlike other types of parameters, type="text" parameters are always optional, and tool
author need to restrict the input with validator elements. By using a profile of at
least 23.0 text parameters that set ``optional="false"`` or define a validator are
indicated as required, but without validator the tool can be executed in any case.
That is a mandatory text parameter should be implemented as:

```
  <param name="mandatory" type="text" optional="false">
    <validator type="empty_field"/>
  </param>
```


The ``area`` boolean attribute can be used to change the ``text`` parameter to a
two-dimensional text area instead of a single line text box.

@@ -3456,7 +3505,7 @@ Describes the parameter type - each different type as different semantics and
the tool form widget is different. Currently valid parameter types are:
``text``,  ``integer``,  ``float``,  ``boolean``,  ``genomebuild``,  ``select``,
``color``,  ``data_column``,  ``hidden``,  ``hidden_data``,  ``baseurl``,
``file``,  ``ftpfile``,  ``data``,  ``data_collection``,  ``library_data``,
``file``,  ``ftpfile``,  ``data``,  ``data_collection``,
``drill_down``. The definition of supported parameter types as defined in the
``parameter_types`` dictionary in
[/lib/galaxy/tools/parameters/basic.py](https://github.com/galaxyproject/galaxy/blob/dev/lib/galaxy/tools/parameters/basic.py).
@@ -3633,7 +3682,7 @@ drop-down menu select list. Used only when the ``type`` attribute value is
            <xs:documentation xml:lang="en">Allow multiple values to be
selected. ``select`` parameters with ``multiple="true"`` are optional by
default. Used only when the ``type`` attribute value is ``data``, ``group_tag``,
or ``select``.</xs:documentation>
or ``select``. Default is ``false``</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="numerical" type="PermissiveBoolean">
@@ -3713,6 +3762,7 @@ allow access to Python code to generate options for a select list. See
      <xs:element name="options" type="ParamOptions"/>
      <xs:element name="validator" type="Validator" />
      <xs:element name="sanitizer" type="Sanitizer"/>
      <xs:element name="default" type="ParamDefault" />
      <xs:element name="help" type="xs:string">
        <xs:annotation>
          <xs:documentation xml:lang="en">Documentation for help</xs:documentation>
@@ -3732,7 +3782,6 @@ allow access to Python code to generate options for a select list. See
      <xs:enumeration value="color"/>
      <xs:enumeration value="boolean"/>
      <xs:enumeration value="genomebuild"/>
      <xs:enumeration value="library_data"/>
      <xs:enumeration value="select"/>
      <xs:enumeration value="data_column"/>
      <xs:enumeration value="hidden"/>
@@ -4098,6 +4147,73 @@ dataset for the contained input of the type specified using the ``type`` tag.
    </xs:attribute>
  </xs:complexType>

  <xs:complexType name="ParamDefault">
    <xs:annotation>
      <xs:documentation xml:lang="en"><![CDATA[
]]>
</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <!-- can have zero or one collection elements -->
      <xs:element name="element" type="ParamDefaultElement" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="collection_type" type="CollectionType" use="optional">
      <xs:annotation>
        <xs:documentation xml:lang="en"><![CDATA[
Collection type for default collection (if param type is data_collection). Simple collection types are
either ``list`` or ``paired``, nested collections are specified as colon separated list of simple
collection types (the most common types are ``list``, ``paired``,
``list:paired``, or ``list:list``).
        ]]></xs:documentation>
      </xs:annotation>
    </xs:attribute>

    <xs:attribute name="location" type="xs:anyURI" gxdocs:added="23.2" use="optional">
      <xs:annotation>
        <xs:documentation xml:lang="en"><![CDATA[
Galaxy-aware URI for the default file. This should only be used with parameters of type "data".
        ]]></xs:documentation>
      </xs:annotation>
    </xs:attribute>

  </xs:complexType>

  <xs:complexType name="ParamDefaultCollection">
    <xs:sequence>
      <xs:element name="element" type="ParamDefaultElement" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>

    <xs:attribute name="collection_type" type="CollectionType" use="optional">
      <xs:annotation>
        <xs:documentation xml:lang="en"><![CDATA[
Collection type for default collection (if param type is data_collection). Simple collection types are
either ``list`` or ``paired``, nested collections are specified as colon separated list of simple
collection types (the most common types are ``list``, ``paired``,
``list:paired``, or ``list:list``).
        ]]></xs:documentation>
      </xs:annotation>
    </xs:attribute>

  </xs:complexType>

  <xs:complexType name="ParamDefaultElement">
    <xs:sequence>
      <xs:element name="collection" type="ParamDefaultCollection" minOccurs="0" maxOccurs="1" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:string">
      <xs:annotation>
        <xs:documentation xml:lang="en">Name (and element identifier) for this element</xs:documentation>
      </xs:annotation>
    </xs:attribute>
    <xs:attribute name="location" type="xs:anyURI" gxdocs:added="23.2" use="optional">
      <xs:annotation>
        <xs:documentation xml:lang="en"><![CDATA[
Galaxy-aware URI for the default file for collection element.
        ]]></xs:documentation>
      </xs:annotation>
    </xs:attribute>
  </xs:complexType>

  <xs:complexType name="ParamOptions">
    <xs:annotation>
      <xs:documentation xml:lang="en"><![CDATA[
@@ -4413,6 +4529,7 @@ Note that each data parameter has automatically a metadata validator that checks
if all non-optional metadata are set, i.e. ``<validator type="metadata/>``.
- ``unspecified_build``: Check of a build is defined.
- ``dataset_ok_validator``: Check if the data set is in state OK.
- ``dataset_metadata_equal``: Check if metadata (given by ``metadata_name``) is equal to a given string value (given by ``value``) or JSON encoded value (given by ``value_json``). ``value_json`` needs to be used for all non string types (e.g. int, float, list, dict).
- ``dataset_metadata_in_range``: Check if a numeric metadata value is within
a given range.
- ``dataset_metadata_in_data_table``: Check if a metadata value is contained in a column of a data table.
@@ -4501,7 +4618,7 @@ use in filenames may not contain ``..``.
          <xs:annotation>
            <xs:documentation xml:lang="en"><![CDATA[
Valid values are: ``expression``, ``regex``, ``in_range``, ``length``,
``metadata``, ``unspecified_build``, ``no_options``, ``empty_field``,
``metadata``, ``metadata_eq`` ``unspecified_build``, ``no_options``, ``empty_field``,
``dataset_metadata_in_data_table``, ``dataset_metadata_not_in_data_table``,
``value_in_data_table``, ``value_not_in_data_table``,
``dataset_ok_validator``, ``dataset_metadata_in_range``.
@@ -4600,6 +4717,18 @@ fields to skip if type is ``metadata``. If not specified, all non-optional
metadata fields will be checked unless ``check`` attribute is specified.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="value" type="xs:string">
          <xs:annotation>
            <xs:documentation xml:lang="en">Value to check the metadata against. Only
applicable to ``dataset_metadata_equal``. Mutually exclusive with ``value_json``.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="value_json" type="xs:string">
          <xs:annotation>
            <xs:documentation xml:lang="en">JSON encoded value to check the metadata against. Only
applicable to ``dataset_metadata_equal``. Mutually exclusive with ``value``.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
        <xs:attribute name="line_startswith" type="xs:string">
          <xs:annotation>
            <xs:documentation xml:lang="en">Deprecated. Used to indicate lines in the file
@@ -6144,6 +6273,7 @@ define.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      <xs:enumeration value="api_key" />
      <xs:enumeration value="entry_point_path_for_label" />
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="ConfigFiles">
@@ -6188,7 +6318,7 @@ tool config.
      xrange = c(NULL, NULL)
      yrange = c(NULL, NULL)
      #for $i, $s in enumerate($series)
          s${i} = read.table("${s.input.file_name}")
          s${i} = read.table("${s.input.get_file_name()}")
          x${i} = s${i}[,${s.xcol}]
          y${i} = s${i}[,${s.ycol}]
          xrange = range(x${i}, xrange)
@@ -7069,6 +7199,7 @@ and ``bibtex`` are the only supported options.</xs:documentation>
      <xs:enumeration value="in_range"/>
      <xs:enumeration value="length"/>
      <xs:enumeration value="metadata"/>
      <xs:enumeration value="dataset_metadata_equal" gxdocs:added="23.1"/>
      <xs:enumeration value="unspecified_build"/>
      <xs:enumeration value="no_options"/>
      <xs:enumeration value="empty_field"/>
@@ -7290,7 +7421,7 @@ information according to a catalog.</xs:documentation>
      <xs:extension base="xs:string">
        <xs:attribute name="type" type="xrefType" use="required">
          <xs:annotation>
            <xs:documentation xml:lang="en">Type of reference - currently ``bio.tools`` and ``bioconductor`` are
            <xs:documentation xml:lang="en">Type of reference - currently ``bio.tools``, ``bioconductor``, and ``biii`` are
the only supported options.</xs:documentation>
          </xs:annotation>
        </xs:attribute>
@@ -7304,6 +7435,7 @@ the only supported options.</xs:documentation>
    <xs:restriction base="xs:string">
      <xs:enumeration value="bio.tools"/>
      <xs:enumeration value="bioconductor"/>
      <xs:enumeration value="biii"/>
      <!--xs:enumeration value="whatelse"/-->
    </xs:restriction>
  </xs:simpleType>
+22 −1
Original line number Diff line number Diff line
@@ -525,7 +525,16 @@ class ToolEvaluator:
        it = []
        for ep in getattr(self.tool, "ports", []):
            ep_dict = {}
            for key in "port", "name", "url", "requires_domain", "protocol":
            for key in (
                "port",
                "name",
                "label",
                "url",
                "requires_domain",
                "protocol",
                "requires_path_in_url",
                "requires_path_in_header_named",
            ):
                val = ep.get(key, None)
                if val is not None and not isinstance(val, bool):
                    val = fill_template(
@@ -658,6 +667,18 @@ class ToolEvaluator:
            elif inject and inject.startswith("oidc_"):
                environment_variable_template = self.get_oidc_token(inject)
                is_template = False
            elif inject and inject == "entry_point_path_for_label" and environment_variable_template:
                from galaxy.managers.interactivetool import InteractiveToolManager

                entry_point_label = environment_variable_template
                matching_eps = [ep for ep in self.job.interactivetool_entry_points if ep.label == entry_point_label]
                if matching_eps:
                    entry_point = matching_eps[0]
                    entry_point_path = InteractiveToolManager(self.app).get_entry_point_path(self.app, entry_point)
                    environment_variable_template = entry_point_path.rstrip("/")
                else:
                    environment_variable_template = ""
                is_template = False
            else:
                is_template = True
            with tempfile.NamedTemporaryFile(dir=directory, prefix="tool_env_", delete=False) as temp:
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
        <container type="docker">quay.io/bgruening/docker-jupyter-notebook:2021-03-05</container>
    </requirements>
    <entry_points>
        <entry_point name="JupyTool interactive tool" label="jupytool" requires_domain="False" requires_path_in_url="True">
        <entry_point name="JupyTool interactive tool" label="jupytool" requires_domain="False">
            <port>8888</port>
            <url>ipython/lab</url>
        </entry_point>