galaxy-test-api 25.0.4__tar.gz → 25.1.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/HISTORY.rst +3 -31
- {galaxy_test_api-25.0.4/galaxy_test_api.egg-info → galaxy_test_api-25.1.dev0}/PKG-INFO +4 -32
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/_framework.py +1 -1
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/conftest.py +5 -6
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/sharable.py +1 -3
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_dataset_collections.py +378 -18
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_datasets.py +3 -7
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_display_applications.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_drs.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_folder_contents.py +7 -9
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_group_roles.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_group_users.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_groups.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_history_contents.py +54 -7
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_item_tags.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_landing.py +69 -10
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_pages.py +6 -8
- galaxy_test_api-25.1.dev0/galaxy_test/api/test_proxy.py +73 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_roles.py +2 -3
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tags.py +1 -2
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tool_execute.py +9 -10
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tools.py +156 -41
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_unprivileged_tools.py +2 -4
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_workflows.py +293 -238
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0/galaxy_test_api.egg-info}/PKG-INFO +4 -32
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/setup.cfg +1 -1
- galaxy_test_api-25.0.4/galaxy_test/api/test_proxy.py +0 -205
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/LICENSE +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/MANIFEST.in +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/README.rst +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/dev-requirements.txt +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/__init__.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/__init__.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/cwl/__init__.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/embed_test_1.gxwf.yml +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/embed_test_1_tool.gxtool.yml +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_authenticate.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_configuration.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_container_resolution.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_datatypes.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_folders.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_framework.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_histories.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_history_contents_provenance.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_jobs.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_libraries.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_library_contents.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_licenses.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_page_revisions.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_short_term_storage.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tool_data.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tools_upload.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_tours.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_users.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_visualizations.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_webhooks.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_workflow_build_module.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_workflow_extraction.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_workflows_cwl.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_workflows_from_yaml.py +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/py.typed +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test_api.egg-info/SOURCES.txt +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test_api.egg-info/dependency_links.txt +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test_api.egg-info/requires.txt +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test_api.egg-info/top_level.txt +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/pyproject.toml +0 -0
- {galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/test-requirements.txt +0 -0
|
@@ -3,39 +3,11 @@ History
|
|
|
3
3
|
|
|
4
4
|
.. to_doc
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
25.
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
---------
|
|
7
|
+
25.1.dev0
|
|
8
|
+
---------
|
|
10
9
|
|
|
11
|
-
=========
|
|
12
|
-
Bug fixes
|
|
13
|
-
=========
|
|
14
|
-
|
|
15
|
-
* Fix PUT /api/workflows for user defined tools by `@mvdbeek <https://github.com/mvdbeek>`_ in `#20987 <https://github.com/galaxyproject/galaxy/pull/20987>`_
|
|
16
|
-
* Run landing request state through validator by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21087 <https://github.com/galaxyproject/galaxy/pull/21087>`_
|
|
17
|
-
* Fix workflow run form input restrictions by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21095 <https://github.com/galaxyproject/galaxy/pull/21095>`_
|
|
18
|
-
* Create new datasets when creating skipped database operation tool outputs by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21142 <https://github.com/galaxyproject/galaxy/pull/21142>`_
|
|
19
|
-
* Fix proxy url validation for non-printable characters by `@davelopez <https://github.com/davelopez>`_ in `#21280 <https://github.com/galaxyproject/galaxy/pull/21280>`_
|
|
20
|
-
|
|
21
|
-
============
|
|
22
|
-
Enhancements
|
|
23
|
-
============
|
|
24
10
|
|
|
25
|
-
* Use job cache also for implicit conversions by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21021 <https://github.com/galaxyproject/galaxy/pull/21021>`_
|
|
26
|
-
* Harden proxy redirect validation by `@davelopez <https://github.com/davelopez>`_ in `#21185 <https://github.com/galaxyproject/galaxy/pull/21185>`_
|
|
27
|
-
|
|
28
|
-
=============
|
|
29
|
-
Other changes
|
|
30
|
-
=============
|
|
31
|
-
|
|
32
|
-
* Backport `Fix proxy endpoint encoding` by `@davelopez <https://github.com/davelopez>`_ in `#21184 <https://github.com/galaxyproject/galaxy/pull/21184>`_
|
|
33
|
-
|
|
34
|
-
-------------------
|
|
35
|
-
25.0.3 (2025-09-23)
|
|
36
|
-
-------------------
|
|
37
|
-
|
|
38
|
-
No recorded changes since last release
|
|
39
11
|
|
|
40
12
|
-------------------
|
|
41
13
|
25.0.2 (2025-08-13)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: galaxy-test-api
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.1.dev0
|
|
4
4
|
Summary: Galaxy API tests
|
|
5
5
|
Home-page: https://github.com/galaxyproject/galaxy
|
|
6
6
|
Author: Galaxy Project and Community
|
|
@@ -54,39 +54,11 @@ History
|
|
|
54
54
|
|
|
55
55
|
.. to_doc
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
25.
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
---------
|
|
58
|
+
25.1.dev0
|
|
59
|
+
---------
|
|
61
60
|
|
|
62
|
-
=========
|
|
63
|
-
Bug fixes
|
|
64
|
-
=========
|
|
65
|
-
|
|
66
|
-
* Fix PUT /api/workflows for user defined tools by `@mvdbeek <https://github.com/mvdbeek>`_ in `#20987 <https://github.com/galaxyproject/galaxy/pull/20987>`_
|
|
67
|
-
* Run landing request state through validator by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21087 <https://github.com/galaxyproject/galaxy/pull/21087>`_
|
|
68
|
-
* Fix workflow run form input restrictions by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21095 <https://github.com/galaxyproject/galaxy/pull/21095>`_
|
|
69
|
-
* Create new datasets when creating skipped database operation tool outputs by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21142 <https://github.com/galaxyproject/galaxy/pull/21142>`_
|
|
70
|
-
* Fix proxy url validation for non-printable characters by `@davelopez <https://github.com/davelopez>`_ in `#21280 <https://github.com/galaxyproject/galaxy/pull/21280>`_
|
|
71
|
-
|
|
72
|
-
============
|
|
73
|
-
Enhancements
|
|
74
|
-
============
|
|
75
61
|
|
|
76
|
-
* Use job cache also for implicit conversions by `@mvdbeek <https://github.com/mvdbeek>`_ in `#21021 <https://github.com/galaxyproject/galaxy/pull/21021>`_
|
|
77
|
-
* Harden proxy redirect validation by `@davelopez <https://github.com/davelopez>`_ in `#21185 <https://github.com/galaxyproject/galaxy/pull/21185>`_
|
|
78
|
-
|
|
79
|
-
=============
|
|
80
|
-
Other changes
|
|
81
|
-
=============
|
|
82
|
-
|
|
83
|
-
* Backport `Fix proxy endpoint encoding` by `@davelopez <https://github.com/davelopez>`_ in `#21184 <https://github.com/galaxyproject/galaxy/pull/21184>`_
|
|
84
|
-
|
|
85
|
-
-------------------
|
|
86
|
-
25.0.3 (2025-09-23)
|
|
87
|
-
-------------------
|
|
88
|
-
|
|
89
|
-
No recorded changes since last release
|
|
90
62
|
|
|
91
63
|
-------------------
|
|
92
64
|
25.0.2 (2025-08-13)
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"""Fixtures for a version of API testing that relies more heavily on pytest injection."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from collections.abc import Iterator
|
|
4
5
|
from dataclasses import dataclass
|
|
5
6
|
from typing import (
|
|
6
7
|
Any,
|
|
7
|
-
Iterator,
|
|
8
|
-
List,
|
|
9
8
|
Optional,
|
|
10
9
|
)
|
|
11
10
|
|
|
@@ -130,8 +129,8 @@ def target_history(
|
|
|
130
129
|
|
|
131
130
|
@pytest.fixture
|
|
132
131
|
def required_tools(
|
|
133
|
-
dataset_populator: DatasetPopulator, history_id: str, required_tool_ids:
|
|
134
|
-
) ->
|
|
132
|
+
dataset_populator: DatasetPopulator, history_id: str, required_tool_ids: list[str]
|
|
133
|
+
) -> list[RequiredTool]:
|
|
135
134
|
tools = []
|
|
136
135
|
for tool_id in required_tool_ids:
|
|
137
136
|
tool = RequiredTool(dataset_populator, tool_id, history_id)
|
|
@@ -140,7 +139,7 @@ def required_tools(
|
|
|
140
139
|
|
|
141
140
|
|
|
142
141
|
@pytest.fixture
|
|
143
|
-
def required_tool(dataset_populator: DatasetPopulator, history_id: str, required_tool_ids:
|
|
142
|
+
def required_tool(dataset_populator: DatasetPopulator, history_id: str, required_tool_ids: list[str]) -> RequiredTool:
|
|
144
143
|
if len(required_tool_ids) != 1:
|
|
145
144
|
raise AssertionError("required_tool fixture must only be used on methods that require a single tool")
|
|
146
145
|
tool_id = required_tool_ids[0]
|
|
@@ -162,7 +161,7 @@ def check_required_tools(anonymous_galaxy_interactor, request):
|
|
|
162
161
|
|
|
163
162
|
|
|
164
163
|
@pytest.fixture
|
|
165
|
-
def required_tool_ids(anonymous_galaxy_interactor, request) ->
|
|
164
|
+
def required_tool_ids(anonymous_galaxy_interactor, request) -> list[str]:
|
|
166
165
|
tool_ids = []
|
|
167
166
|
for marker in request.node.iter_markers():
|
|
168
167
|
if marker.name == "requires_tool_id":
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
|
-
Dict,
|
|
4
|
-
List,
|
|
5
3
|
)
|
|
6
4
|
from unittest import SkipTest
|
|
7
5
|
from uuid import uuid4
|
|
@@ -63,7 +61,7 @@ class SharingApiTests(UsesApiTestCaseMixin):
|
|
|
63
61
|
sharing_response = self._get_resource_sharing_status(resource_id)
|
|
64
62
|
assert not sharing_response["users_shared_with"]
|
|
65
63
|
|
|
66
|
-
payload:
|
|
64
|
+
payload: dict[str, list[str]] = {"user_ids": []}
|
|
67
65
|
sharing_response = self._set_resource_sharing(resource_id, action="share_with_users", payload=payload)
|
|
68
66
|
assert not sharing_response["users_shared_with"]
|
|
69
67
|
|
{galaxy_test_api-25.0.4 → galaxy_test_api-25.1.dev0}/galaxy_test/api/test_dataset_collections.py
RENAMED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import zipfile
|
|
3
3
|
from io import BytesIO
|
|
4
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
5
|
from urllib.parse import quote
|
|
6
6
|
|
|
7
|
+
from galaxy.schema.schema import SampleSheetColumnDefinitions
|
|
8
|
+
from galaxy.util import galaxy_root_path
|
|
7
9
|
from galaxy.util.unittest_utils import skip_if_github_down
|
|
8
|
-
from galaxy_test.base.api_asserts import
|
|
10
|
+
from galaxy_test.base.api_asserts import (
|
|
11
|
+
assert_has_key,
|
|
12
|
+
assert_object_id_error,
|
|
13
|
+
assert_status_code_is,
|
|
14
|
+
)
|
|
9
15
|
from galaxy_test.base.decorators import requires_new_user
|
|
10
16
|
from galaxy_test.base.populators import (
|
|
11
17
|
DatasetCollectionPopulator,
|
|
@@ -13,6 +19,32 @@ from galaxy_test.base.populators import (
|
|
|
13
19
|
)
|
|
14
20
|
from ._framework import ApiTestCase
|
|
15
21
|
|
|
22
|
+
# copy of unit test definition in test_sample_sheet_workbook.py - maybe just serialize it as JSON?
|
|
23
|
+
TEST_COLUMN_DEFINITIONS_1: SampleSheetColumnDefinitions = [
|
|
24
|
+
{
|
|
25
|
+
"name": "replicate number",
|
|
26
|
+
"type": "int",
|
|
27
|
+
"description": "The replicate number of this sample.",
|
|
28
|
+
"default_value": 0,
|
|
29
|
+
"optional": False,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "treatment",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"restrictions": ["treatment1", "treatment2", "none"],
|
|
35
|
+
"description": "The treatment code for this sample.",
|
|
36
|
+
"default_value": "none",
|
|
37
|
+
"optional": False,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "is control?",
|
|
41
|
+
"type": "boolean",
|
|
42
|
+
"description": "Was this sample a control? If TRUE, please ensure treatment is set to none.",
|
|
43
|
+
"default_value": True,
|
|
44
|
+
"optional": False,
|
|
45
|
+
},
|
|
46
|
+
]
|
|
47
|
+
|
|
16
48
|
|
|
17
49
|
class TestDatasetCollectionsApi(ApiTestCase):
|
|
18
50
|
dataset_populator: DatasetPopulator
|
|
@@ -220,6 +252,249 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
220
252
|
create_response = self._post("dataset_collections", payload)
|
|
221
253
|
self._assert_status_code_is(create_response, 400)
|
|
222
254
|
|
|
255
|
+
def test_sample_sheet_column_definition_problems(self, history_id):
|
|
256
|
+
contents = [
|
|
257
|
+
("sample1", "1\t2\t3"),
|
|
258
|
+
("sample2", "4\t5\t6"),
|
|
259
|
+
]
|
|
260
|
+
sample_sheet_identifiers = self.dataset_collection_populator.list_identifiers(history_id, contents)
|
|
261
|
+
payload = dict(
|
|
262
|
+
name="my cool sample sheet",
|
|
263
|
+
instance_type="history",
|
|
264
|
+
history_id=history_id,
|
|
265
|
+
element_identifiers=sample_sheet_identifiers,
|
|
266
|
+
collection_type="sample_sheet",
|
|
267
|
+
column_definitions=[{"type": "int", "name": "replicate", "optional": False}],
|
|
268
|
+
rows={"sample1": [42], "sample2": [45]},
|
|
269
|
+
)
|
|
270
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
271
|
+
self._check_create_response(create_response)
|
|
272
|
+
payload["column_definitions"] = [{"type": "intx"}]
|
|
273
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
274
|
+
assert_status_code_is(create_response, 400)
|
|
275
|
+
payload["column_definitions"] = [{"typex": "int"}]
|
|
276
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
277
|
+
assert_status_code_is(create_response, 400)
|
|
278
|
+
payload["column_definitions"] = [{"type": "int", "restrictions": "wrongtype", "name": "replicate"}]
|
|
279
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
280
|
+
assert_status_code_is(create_response, 400)
|
|
281
|
+
payload["column_definitions"] = [
|
|
282
|
+
{"type": "int", "name": "replicate", "validators": [{"type": "expression", "expression": "False"}]}
|
|
283
|
+
]
|
|
284
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
285
|
+
assert_status_code_is(create_response, 400)
|
|
286
|
+
|
|
287
|
+
def test_sample_sheet_element_identifier_column_type(self, history_id):
|
|
288
|
+
contents = [
|
|
289
|
+
("sample1", "1\t2\t3"),
|
|
290
|
+
("sample2", "4\t5\t6"),
|
|
291
|
+
]
|
|
292
|
+
sample_sheet_identifiers = self.dataset_collection_populator.list_identifiers(history_id, contents)
|
|
293
|
+
payload = dict(
|
|
294
|
+
name="my cool sample sheet",
|
|
295
|
+
instance_type="history",
|
|
296
|
+
history_id=history_id,
|
|
297
|
+
element_identifiers=sample_sheet_identifiers,
|
|
298
|
+
collection_type="sample_sheet",
|
|
299
|
+
column_definitions=[{"type": "element_identifier", "name": "matched_element", "optional": False}],
|
|
300
|
+
rows={"sample1": ["sample2"], "sample2": ["sample1"]},
|
|
301
|
+
)
|
|
302
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
303
|
+
self._check_create_response(create_response)
|
|
304
|
+
|
|
305
|
+
# should not allow collection creation if element identifiers are not matching
|
|
306
|
+
payload["rows"] = {"sample1": ["noinsamplesheet"], "sample2": ["noinsamplesheet"]}
|
|
307
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
308
|
+
assert_status_code_is(create_response, 400)
|
|
309
|
+
|
|
310
|
+
def test_sample_sheet_of_pairs_creation(self, history_id):
|
|
311
|
+
contents = [
|
|
312
|
+
"1\t2\t3",
|
|
313
|
+
"4\t5\t6",
|
|
314
|
+
]
|
|
315
|
+
pair_identifiers = self.dataset_collection_populator.pair_identifiers(history_id, contents)
|
|
316
|
+
identifiers = [
|
|
317
|
+
{
|
|
318
|
+
"name": "sample1",
|
|
319
|
+
"collection_type": "paired",
|
|
320
|
+
"src": "new_collection",
|
|
321
|
+
"element_identifiers": pair_identifiers,
|
|
322
|
+
}
|
|
323
|
+
]
|
|
324
|
+
payload = dict(
|
|
325
|
+
name="my cool sample sheet",
|
|
326
|
+
instance_type="history",
|
|
327
|
+
history_id=history_id,
|
|
328
|
+
element_identifiers=identifiers,
|
|
329
|
+
collection_type="sample_sheet:paired",
|
|
330
|
+
column_definitions=[{"type": "int", "name": "replicate", "default_value": 0, "optional": False}],
|
|
331
|
+
rows={"sample1": [42]},
|
|
332
|
+
)
|
|
333
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
334
|
+
print(create_response.json())
|
|
335
|
+
self._check_create_response(create_response)
|
|
336
|
+
dataset_collection = create_response.json()
|
|
337
|
+
assert dataset_collection["collection_type"] == "sample_sheet:paired"
|
|
338
|
+
assert dataset_collection["name"] == "my cool sample sheet"
|
|
339
|
+
returned_collections = dataset_collection["elements"]
|
|
340
|
+
assert len(returned_collections) == 1, dataset_collection
|
|
341
|
+
sheet_row_0_element = returned_collections[0]
|
|
342
|
+
self._assert_has_keys(sheet_row_0_element, "element_index", "columns")
|
|
343
|
+
columns = sheet_row_0_element["columns"]
|
|
344
|
+
assert len(columns) == 1
|
|
345
|
+
assert columns[0] == 42
|
|
346
|
+
|
|
347
|
+
hdca_id = dataset_collection["id"]
|
|
348
|
+
dataset_collection_url = f"/api/dataset_collections/{hdca_id}"
|
|
349
|
+
dataset_collection = self._get(dataset_collection_url).json()
|
|
350
|
+
assert dataset_collection["id"] == hdca_id
|
|
351
|
+
assert dataset_collection["collection_type"] == "sample_sheet:paired"
|
|
352
|
+
assert dataset_collection["column_definitions"] is not None
|
|
353
|
+
|
|
354
|
+
def test_sample_sheet_validating_against_column_definition(self, history_id):
|
|
355
|
+
contents = [
|
|
356
|
+
("sample1", "1\t2\t3"),
|
|
357
|
+
("sample2", "4\t5\t6"),
|
|
358
|
+
]
|
|
359
|
+
sample_sheet_identifiers = self.dataset_collection_populator.list_identifiers(history_id, contents)
|
|
360
|
+
payload = dict(
|
|
361
|
+
name="my cool sample sheet",
|
|
362
|
+
instance_type="history",
|
|
363
|
+
history_id=history_id,
|
|
364
|
+
element_identifiers=sample_sheet_identifiers,
|
|
365
|
+
collection_type="sample_sheet",
|
|
366
|
+
column_definitions=[{"type": "int", "name": "replicate", "default_value": 0, "optional": False}],
|
|
367
|
+
rows={"sample1": [42], "sample2": [45]},
|
|
368
|
+
)
|
|
369
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
370
|
+
print(create_response.json())
|
|
371
|
+
self._check_create_response(create_response)
|
|
372
|
+
# now the datatype of the row data is wrong....
|
|
373
|
+
payload["column_definitions"] = [
|
|
374
|
+
{"type": "string", "name": "replicate", "default_value": "", "optional": False}
|
|
375
|
+
]
|
|
376
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
377
|
+
assert_status_code_is(create_response, 400)
|
|
378
|
+
print(create_response.json())
|
|
379
|
+
|
|
380
|
+
# now the row values are too small for the supplied validator
|
|
381
|
+
payload["column_definitions"] = [
|
|
382
|
+
{"type": "int", "name": "replicate", "validators": [{"type": "in_range", "min": 60}]}
|
|
383
|
+
]
|
|
384
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
385
|
+
assert_status_code_is(create_response, 400)
|
|
386
|
+
|
|
387
|
+
def test_sample_sheet_requires_columns(self, history_id):
|
|
388
|
+
contents = [
|
|
389
|
+
("sample1", "1\t2\t3"),
|
|
390
|
+
("sample2", "4\t5\t6"),
|
|
391
|
+
]
|
|
392
|
+
sample_sheet_identifiers = self.dataset_collection_populator.list_identifiers(history_id, contents)
|
|
393
|
+
payload = dict(
|
|
394
|
+
name="my cool sample sheet",
|
|
395
|
+
instance_type="history",
|
|
396
|
+
history_id=history_id,
|
|
397
|
+
element_identifiers=sample_sheet_identifiers,
|
|
398
|
+
collection_type="sample_sheet",
|
|
399
|
+
column_definitions=[{"type": "int", "name": "replicate", "optional": False}],
|
|
400
|
+
rows={"sample1": [42], "sample2": [45]},
|
|
401
|
+
)
|
|
402
|
+
create_response = self._post("dataset_collections", payload, json=True)
|
|
403
|
+
dataset_collection = self._check_create_response(create_response)
|
|
404
|
+
|
|
405
|
+
self._assert_has_keys(dataset_collection, "collection_type", "column_definitions")
|
|
406
|
+
column_definitions = dataset_collection["column_definitions"]
|
|
407
|
+
assert len(column_definitions) == 1
|
|
408
|
+
self._assert_has_keys(column_definitions[0], "type")
|
|
409
|
+
assert column_definitions[0]["type"] == "int"
|
|
410
|
+
|
|
411
|
+
# TODO: restore assertion and test before merging...
|
|
412
|
+
# assert something about column definition here....
|
|
413
|
+
assert dataset_collection["collection_type"] == "sample_sheet"
|
|
414
|
+
assert dataset_collection["name"] == "my cool sample sheet"
|
|
415
|
+
returned_collections = dataset_collection["elements"]
|
|
416
|
+
assert len(returned_collections) == 2, dataset_collection
|
|
417
|
+
sheet_row_0_element = returned_collections[0]
|
|
418
|
+
self._assert_has_keys(sheet_row_0_element, "element_index", "columns")
|
|
419
|
+
record_pos_0_object = sheet_row_0_element["object"]
|
|
420
|
+
self._assert_has_keys(record_pos_0_object, "name", "history_content_type")
|
|
421
|
+
row_0 = sheet_row_0_element["columns"]
|
|
422
|
+
assert row_0[0] == 42
|
|
423
|
+
|
|
424
|
+
sheet_row_1_element = returned_collections[1]
|
|
425
|
+
self._assert_has_keys(sheet_row_1_element, "element_index", "columns")
|
|
426
|
+
row_1 = sheet_row_1_element["columns"]
|
|
427
|
+
assert row_1[0] == 45
|
|
428
|
+
# TODO: test case where column definition does not match supplied data
|
|
429
|
+
|
|
430
|
+
def test_workbook_download(self):
|
|
431
|
+
xlsx_file = self.dataset_collection_populator.download_workbook(
|
|
432
|
+
"sample_sheet",
|
|
433
|
+
[
|
|
434
|
+
{"name": "condition", "type": "string", "default_value": "", "optional": False},
|
|
435
|
+
{"name": "replicate", "type": "int", "default_value": 0, "optional": False},
|
|
436
|
+
],
|
|
437
|
+
)
|
|
438
|
+
self._assert_file_looks_like_xlsx(xlsx_file)
|
|
439
|
+
|
|
440
|
+
def test_workbook_download_for_collection(self):
|
|
441
|
+
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
442
|
+
hdca_id = self.dataset_collection_populator.create_list_in_history(
|
|
443
|
+
history_id, contents=[("sample1", "sample1 contents")], wait=True
|
|
444
|
+
).json()["outputs"][0]["id"]
|
|
445
|
+
|
|
446
|
+
xlsx_file = self.dataset_collection_populator.download_workbook_for_collection(
|
|
447
|
+
hdca_id,
|
|
448
|
+
[
|
|
449
|
+
{"name": "condition", "type": "string", "default_value": "", "optional": False},
|
|
450
|
+
{"name": "replicate", "type": "int", "default_value": 0, "optional": False},
|
|
451
|
+
],
|
|
452
|
+
)
|
|
453
|
+
self._assert_file_looks_like_xlsx(xlsx_file)
|
|
454
|
+
|
|
455
|
+
def _assert_file_looks_like_xlsx(self, xlsx_file: str):
|
|
456
|
+
# Check the file header
|
|
457
|
+
with open(xlsx_file, "rb") as file:
|
|
458
|
+
header = file.read(4)
|
|
459
|
+
# The ZIP file signature is 0x50 0x4B 0x03 0x04
|
|
460
|
+
return header == b"\x50\x4b\x03\x04"
|
|
461
|
+
|
|
462
|
+
def test_workbook_parse(self):
|
|
463
|
+
xlsx_path = Path(galaxy_root_path) / "lib" / "galaxy" / "model" / "unittest_utils" / "filled_in_workbook_1.xlsx"
|
|
464
|
+
example_as_bytes = xlsx_path.read_bytes()
|
|
465
|
+
response = self.dataset_collection_populator.parse_workbook(
|
|
466
|
+
example_as_bytes, "sample_sheet", TEST_COLUMN_DEFINITIONS_1
|
|
467
|
+
)
|
|
468
|
+
assert_has_key(response, "rows")
|
|
469
|
+
rows = response["rows"]
|
|
470
|
+
assert rows[0]["url"] == "https://zenodo.org/records/3263975/files/DRR000770.fastqsanger.gz"
|
|
471
|
+
assert rows[0]["replicate number"] == 1
|
|
472
|
+
assert rows[0]["treatment"] == "treatment1"
|
|
473
|
+
assert rows[0]["is control?"] is False
|
|
474
|
+
assert rows[1]["replicate number"] == 2
|
|
475
|
+
assert rows[1]["treatment"] == "treatment1"
|
|
476
|
+
|
|
477
|
+
def test_workbook_parse_for_collection(self):
|
|
478
|
+
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
479
|
+
hdca_id = self.dataset_collection_populator.create_list_in_history(
|
|
480
|
+
history_id, contents=[("sample1", "sample1 contents")], wait=True
|
|
481
|
+
).json()["outputs"][0]["id"]
|
|
482
|
+
|
|
483
|
+
xlsx_path = (
|
|
484
|
+
Path(galaxy_root_path)
|
|
485
|
+
/ "lib"
|
|
486
|
+
/ "galaxy"
|
|
487
|
+
/ "model"
|
|
488
|
+
/ "unittest_utils"
|
|
489
|
+
/ "filled_in_workbook_from_collection.xlsx"
|
|
490
|
+
)
|
|
491
|
+
example_as_bytes = xlsx_path.read_bytes()
|
|
492
|
+
response = self.dataset_collection_populator.parse_workflow_for_collection(
|
|
493
|
+
hdca_id, example_as_bytes, TEST_COLUMN_DEFINITIONS_1
|
|
494
|
+
)
|
|
495
|
+
assert_has_key(response, "rows")
|
|
496
|
+
assert_has_key(response, "elements")
|
|
497
|
+
|
|
223
498
|
def test_list_download(self):
|
|
224
499
|
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
225
500
|
fetch_response = self.dataset_collection_populator.create_list_in_history(
|
|
@@ -401,7 +676,7 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
401
676
|
"__files": {"files_0|file_data": open(self.test_data_resolver.get_filename("4.bed"))},
|
|
402
677
|
}
|
|
403
678
|
self.dataset_populator.fetch(payload)
|
|
404
|
-
hdca = self.
|
|
679
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
405
680
|
assert hdca["name"] == "Test upload"
|
|
406
681
|
hdca_tags = hdca["tags"]
|
|
407
682
|
assert len(hdca_tags) == 1
|
|
@@ -431,19 +706,19 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
431
706
|
"__files": {"files_0|file_data": open(self.test_data_resolver.get_filename("4.bed"))},
|
|
432
707
|
}
|
|
433
708
|
self.dataset_populator.fetch(payload)
|
|
434
|
-
hdca = self.
|
|
709
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
435
710
|
assert hdca["name"] == "Test upload"
|
|
436
711
|
assert len(hdca["elements"]) == 1, hdca
|
|
437
712
|
element0 = hdca["elements"][0]
|
|
438
713
|
assert element0["element_identifier"] == "samp1"
|
|
439
714
|
|
|
440
|
-
@skip_if_github_down
|
|
441
715
|
def test_upload_collection_from_url(self):
|
|
442
716
|
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
443
717
|
elements = [
|
|
444
718
|
{
|
|
445
719
|
"src": "url",
|
|
446
|
-
"url":
|
|
720
|
+
"url": self.dataset_populator.base64_url_for_string("hello world"),
|
|
721
|
+
"name": "hello.txt",
|
|
447
722
|
"info": "my cool bed",
|
|
448
723
|
}
|
|
449
724
|
]
|
|
@@ -459,11 +734,11 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
459
734
|
"targets": targets,
|
|
460
735
|
}
|
|
461
736
|
self.dataset_populator.fetch(payload)
|
|
462
|
-
hdca = self.
|
|
737
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
463
738
|
assert len(hdca["elements"]) == 1, hdca
|
|
464
739
|
element0 = hdca["elements"][0]
|
|
465
|
-
assert element0["element_identifier"] == "
|
|
466
|
-
assert element0["object"]["file_size"] ==
|
|
740
|
+
assert element0["element_identifier"] == "hello.txt"
|
|
741
|
+
assert element0["object"]["file_size"] == 11
|
|
467
742
|
|
|
468
743
|
def test_upload_collection_deferred(self):
|
|
469
744
|
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
@@ -487,7 +762,7 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
487
762
|
"targets": targets,
|
|
488
763
|
}
|
|
489
764
|
self.dataset_populator.fetch(payload)
|
|
490
|
-
hdca = self.
|
|
765
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
491
766
|
assert len(hdca["elements"]) == 1, hdca
|
|
492
767
|
element0 = hdca["elements"][0]
|
|
493
768
|
assert element0["element_identifier"] == "4.bed"
|
|
@@ -511,21 +786,62 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
511
786
|
"targets": targets,
|
|
512
787
|
}
|
|
513
788
|
self.dataset_populator.fetch(payload, assert_ok=False, wait=True)
|
|
514
|
-
hdca = self.
|
|
789
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
515
790
|
assert hdca["populated"] is False
|
|
516
791
|
assert "bagit.txt" in hdca["populated_state_message"], hdca
|
|
517
792
|
|
|
793
|
+
def test_upload_flat_sample_sheet(self):
|
|
794
|
+
upload_flat_sample_sheet(self.dataset_populator)
|
|
795
|
+
|
|
796
|
+
def test_upload_sample_sheet_paired(self):
|
|
797
|
+
column_definitions = [{"type": "int", "name": "replicate", "optional": False, "default_value": 0}]
|
|
798
|
+
with self.dataset_populator.test_history(require_new=False) as history_id:
|
|
799
|
+
elements = [
|
|
800
|
+
{
|
|
801
|
+
"name": "sample1",
|
|
802
|
+
"row": [42],
|
|
803
|
+
"elements": [
|
|
804
|
+
{
|
|
805
|
+
"src": "url",
|
|
806
|
+
"url": self.dataset_populator.base64_url_for_string("hello world forward"),
|
|
807
|
+
"info": "my cool hello world forward",
|
|
808
|
+
"name": "forward",
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
"src": "url",
|
|
812
|
+
"url": self.dataset_populator.base64_url_for_string("hello world reverse"),
|
|
813
|
+
"info": "my cool hello world reverse",
|
|
814
|
+
"name": "forward",
|
|
815
|
+
},
|
|
816
|
+
],
|
|
817
|
+
}
|
|
818
|
+
]
|
|
819
|
+
targets = [
|
|
820
|
+
{
|
|
821
|
+
"destination": {"type": "hdca"},
|
|
822
|
+
"elements": elements,
|
|
823
|
+
"collection_type": "sample_sheet:paired",
|
|
824
|
+
"column_definitions": column_definitions,
|
|
825
|
+
}
|
|
826
|
+
]
|
|
827
|
+
payload = {
|
|
828
|
+
"history_id": history_id,
|
|
829
|
+
"targets": targets,
|
|
830
|
+
}
|
|
831
|
+
self.dataset_populator.fetch(payload)
|
|
832
|
+
hdca = assert_one_collection_created_in_history(self.dataset_populator, history_id)
|
|
833
|
+
assert len(hdca["elements"]) == 1, hdca
|
|
834
|
+
element0 = hdca["elements"][0]
|
|
835
|
+
assert element0["element_identifier"] == "sample1"
|
|
836
|
+
assert element0["columns"][0] == 42
|
|
837
|
+
|
|
518
838
|
def _assert_one_collection_created_in_history(self, history_id: str):
|
|
519
|
-
|
|
520
|
-
self._assert_status_code_is(contents_response, 200)
|
|
521
|
-
contents = contents_response.json()
|
|
839
|
+
contents = self.dataset_populator.get_history_contents_of_type(history_id, "dataset_collections")
|
|
522
840
|
assert len(contents) == 1
|
|
523
841
|
hdca = contents[0]
|
|
524
842
|
assert hdca["history_content_type"] == "dataset_collection"
|
|
525
843
|
hdca_id = hdca["id"]
|
|
526
|
-
|
|
527
|
-
self._assert_status_code_is(collection_response, 200)
|
|
528
|
-
return collection_response.json()
|
|
844
|
+
return self.dataset_populator.get_history_collection_details(history_id, content_id=hdca_id)
|
|
529
845
|
|
|
530
846
|
def _check_create_response(self, create_response):
|
|
531
847
|
self._assert_status_code_is(create_response, 200)
|
|
@@ -728,7 +1044,7 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
728
1044
|
self._assert_status_code_is(response, 200)
|
|
729
1045
|
hdca_list_id = response.json()["outputs"][0]["id"]
|
|
730
1046
|
converters = self._get("dataset_collections/" + hdca_list_id + "/suitable_converters")
|
|
731
|
-
actual:
|
|
1047
|
+
actual: list[str] = []
|
|
732
1048
|
for converter in converters.json():
|
|
733
1049
|
actual.append(converter["tool_id"])
|
|
734
1050
|
assert actual == []
|
|
@@ -798,3 +1114,47 @@ class TestDatasetCollectionsApi(ApiTestCase):
|
|
|
798
1114
|
assert "contents_url" in matches[0]
|
|
799
1115
|
|
|
800
1116
|
return matches[0]["contents_url"]
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
def upload_flat_sample_sheet(dataset_populator: DatasetPopulator):
|
|
1120
|
+
column_definitions = [{"type": "int", "name": "replicate", "optional": False, "default_value": 0}]
|
|
1121
|
+
with dataset_populator.test_history(require_new=False) as history_id:
|
|
1122
|
+
elements = [
|
|
1123
|
+
{
|
|
1124
|
+
"src": "url",
|
|
1125
|
+
"url": dataset_populator.base64_url_for_string("hello world"),
|
|
1126
|
+
"info": "my cool hello world",
|
|
1127
|
+
"name": "sample1",
|
|
1128
|
+
"row": [42],
|
|
1129
|
+
}
|
|
1130
|
+
]
|
|
1131
|
+
targets = [
|
|
1132
|
+
{
|
|
1133
|
+
"destination": {"type": "hdca"},
|
|
1134
|
+
"elements": elements,
|
|
1135
|
+
"collection_type": "sample_sheet",
|
|
1136
|
+
"column_definitions": column_definitions,
|
|
1137
|
+
}
|
|
1138
|
+
]
|
|
1139
|
+
payload = {
|
|
1140
|
+
"history_id": history_id,
|
|
1141
|
+
"targets": targets,
|
|
1142
|
+
}
|
|
1143
|
+
dataset_populator.fetch(payload)
|
|
1144
|
+
hdca = assert_one_collection_created_in_history(dataset_populator, history_id)
|
|
1145
|
+
assert len(hdca["elements"]) == 1, hdca
|
|
1146
|
+
element0 = hdca["elements"][0]
|
|
1147
|
+
assert element0["element_identifier"] == "sample1"
|
|
1148
|
+
assert element0["columns"][0] == 42
|
|
1149
|
+
object0 = element0["object"]
|
|
1150
|
+
assert object0["state"] == "ok"
|
|
1151
|
+
assert hdca["column_definitions"] is not None
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
def assert_one_collection_created_in_history(dataset_populator: DatasetPopulator, history_id: str):
|
|
1155
|
+
contents = dataset_populator.get_history_contents_of_type(history_id, "dataset_collections")
|
|
1156
|
+
assert len(contents) == 1
|
|
1157
|
+
hdca = contents[0]
|
|
1158
|
+
assert hdca["history_content_type"] == "dataset_collection"
|
|
1159
|
+
hdca_id = hdca["id"]
|
|
1160
|
+
return dataset_populator.get_history_collection_details(history_id, content_id=hdca_id)
|