django-to-galaxy 0.7.0.0__py3-none-any.whl
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.
- django_to_galaxy/__init__.py +1 -0
- django_to_galaxy/admin/__init__.py +13 -0
- django_to_galaxy/admin/galaxy_element.py +6 -0
- django_to_galaxy/admin/galaxy_instance.py +26 -0
- django_to_galaxy/admin/galaxy_output_file.py +79 -0
- django_to_galaxy/admin/galaxy_user.py +183 -0
- django_to_galaxy/admin/history.py +91 -0
- django_to_galaxy/admin/invocation.py +154 -0
- django_to_galaxy/admin/tag.py +17 -0
- django_to_galaxy/admin/utils.py +116 -0
- django_to_galaxy/admin/workflow.py +131 -0
- django_to_galaxy/api/__init__.py +0 -0
- django_to_galaxy/api/serializers/asymetricslugrelatedfield.py +31 -0
- django_to_galaxy/api/serializers/create_dataset_collection.py +118 -0
- django_to_galaxy/api/serializers/create_history.py +6 -0
- django_to_galaxy/api/serializers/galaxy_instance.py +10 -0
- django_to_galaxy/api/serializers/galaxy_output_file.py +17 -0
- django_to_galaxy/api/serializers/galaxy_user.py +20 -0
- django_to_galaxy/api/serializers/history.py +17 -0
- django_to_galaxy/api/serializers/invocation.py +22 -0
- django_to_galaxy/api/serializers/invoke_workflow.py +24 -0
- django_to_galaxy/api/serializers/upload_to_history.py +25 -0
- django_to_galaxy/api/serializers/workflow.py +41 -0
- django_to_galaxy/api/urls.py +53 -0
- django_to_galaxy/api/views/create_dataset_collection.py +461 -0
- django_to_galaxy/api/views/create_history.py +23 -0
- django_to_galaxy/api/views/galaxy_instance.py +13 -0
- django_to_galaxy/api/views/galaxy_output_file.py +15 -0
- django_to_galaxy/api/views/galaxy_user.py +13 -0
- django_to_galaxy/api/views/history.py +14 -0
- django_to_galaxy/api/views/invocation.py +45 -0
- django_to_galaxy/api/views/invoke_workflow.py +181 -0
- django_to_galaxy/api/views/upload_to_history.py +78 -0
- django_to_galaxy/api/views/workflow.py +14 -0
- django_to_galaxy/apps.py +6 -0
- django_to_galaxy/migrations/0001_new_initial.py +171 -0
- django_to_galaxy/migrations/0002_rename_state_history_galaxy_state_and_more.py +37 -0
- django_to_galaxy/migrations/0003_invocation_create_time.py +20 -0
- django_to_galaxy/migrations/0004_alter_galaxyuser_email_galaxyoutputfile.py +46 -0
- django_to_galaxy/migrations/0005_alter_galaxyoutputfile_invocation_and_more.py +37 -0
- django_to_galaxy/migrations/0006_tag_history_tags_workflow_tags.py +42 -0
- django_to_galaxy/migrations/0007_format_alter_history_tags_alter_workflow_tags_and_more.py +63 -0
- django_to_galaxy/migrations/0008_workflowinput_label.py +21 -0
- django_to_galaxy/migrations/0009_galaxyoutputfile_unique_galaxy_id_per_invocation.py +20 -0
- django_to_galaxy/migrations/0010_workflow__is_meta_workflow__step_jobs_count.py +23 -0
- django_to_galaxy/migrations/0011_rename__step_jobs_count_workflow__step_count_and_more.py +23 -0
- django_to_galaxy/migrations/0012_workflowinput_collection_type_and_more.py +136 -0
- django_to_galaxy/migrations/__init__.py +0 -0
- django_to_galaxy/models/__init__.py +8 -0
- django_to_galaxy/models/accepted_input.py +139 -0
- django_to_galaxy/models/galaxy_element.py +52 -0
- django_to_galaxy/models/galaxy_instance.py +29 -0
- django_to_galaxy/models/galaxy_output_file.py +53 -0
- django_to_galaxy/models/galaxy_user.py +94 -0
- django_to_galaxy/models/history.py +73 -0
- django_to_galaxy/models/invocation.py +251 -0
- django_to_galaxy/models/workflow.py +440 -0
- django_to_galaxy/schemas/__init__.py +0 -0
- django_to_galaxy/schemas/dataset.py +16 -0
- django_to_galaxy/settings.py +8 -0
- django_to_galaxy/templates/admin/import_workflows.html +89 -0
- django_to_galaxy/urls.py +3 -0
- django_to_galaxy/utils.py +61 -0
- django_to_galaxy/version.py +3 -0
- django_to_galaxy-0.7.0.0.dist-info/METADATA +17 -0
- django_to_galaxy-0.7.0.0.dist-info/RECORD +68 -0
- django_to_galaxy-0.7.0.0.dist-info/WHEEL +4 -0
- django_to_galaxy-0.7.0.0.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .version import __version__ # noqa
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .galaxy_instance import GalaxyInstanceAdmin # noqa
|
|
2
|
+
from .galaxy_user import GalaxyUserAdmin # noqa
|
|
3
|
+
from .galaxy_output_file import GalaxyOutputFileAdmin # noqa
|
|
4
|
+
from .history import HistoryAdmin # noqa
|
|
5
|
+
from .invocation import InvocationAdmin # noqa
|
|
6
|
+
from .workflow import ( # noqa
|
|
7
|
+
WorkflowAdmin, # noqa
|
|
8
|
+
WorkflowInputAdmin, # noqa
|
|
9
|
+
FormatAdmin, # noqa
|
|
10
|
+
WorkflowInputTextOptionAdmin, # noqa
|
|
11
|
+
) # noqa
|
|
12
|
+
from .tag import TagAdmin # noqa
|
|
13
|
+
from .utils import * # noqa
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from django.urls import reverse
|
|
3
|
+
from django.utils.html import format_html
|
|
4
|
+
from django.utils.http import urlencode
|
|
5
|
+
|
|
6
|
+
from django_to_galaxy.models.galaxy_instance import GalaxyInstance
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@admin.register(GalaxyInstance)
|
|
10
|
+
class GalaxyInstanceAdmin(admin.ModelAdmin):
|
|
11
|
+
list_display = ("url", "name", "get_registered_users", "is_online")
|
|
12
|
+
|
|
13
|
+
def get_registered_users(self, obj):
|
|
14
|
+
count = obj.users.count()
|
|
15
|
+
url = (
|
|
16
|
+
reverse("admin:django_to_galaxy_galaxyuser_changelist")
|
|
17
|
+
+ "?"
|
|
18
|
+
+ urlencode({"galaxy_instance__id": f"{obj.id}"})
|
|
19
|
+
)
|
|
20
|
+
return format_html('<a href="{}">{}</a>', url, count)
|
|
21
|
+
|
|
22
|
+
def is_online(self, obj):
|
|
23
|
+
return obj.is_online()
|
|
24
|
+
|
|
25
|
+
get_registered_users.short_description = "Registered users"
|
|
26
|
+
is_online.boolean = True
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin, messages
|
|
4
|
+
from django.utils.translation import ngettext
|
|
5
|
+
|
|
6
|
+
from django_to_galaxy.models.galaxy_output_file import GalaxyOutputFile
|
|
7
|
+
|
|
8
|
+
from .galaxy_element import GalaxyElementAdmin
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@admin.register(GalaxyOutputFile)
|
|
12
|
+
class GalaxyOutputFileAdmin(GalaxyElementAdmin):
|
|
13
|
+
list_display = (
|
|
14
|
+
"id",
|
|
15
|
+
"galaxy_id",
|
|
16
|
+
"workflow_name",
|
|
17
|
+
"history_name",
|
|
18
|
+
"galaxy_state",
|
|
19
|
+
"src",
|
|
20
|
+
"invocation",
|
|
21
|
+
)
|
|
22
|
+
readonly_fields = (
|
|
23
|
+
"id",
|
|
24
|
+
"galaxy_id",
|
|
25
|
+
"workflow_name",
|
|
26
|
+
"history_name",
|
|
27
|
+
"galaxy_state",
|
|
28
|
+
"src",
|
|
29
|
+
"invocation",
|
|
30
|
+
)
|
|
31
|
+
actions = ["synchronize_file"]
|
|
32
|
+
|
|
33
|
+
def _get_message_output_file_synchronize(
|
|
34
|
+
self,
|
|
35
|
+
request,
|
|
36
|
+
output_files: List[GalaxyOutputFile],
|
|
37
|
+
message_singular: str,
|
|
38
|
+
message_plural: str,
|
|
39
|
+
message_type: int,
|
|
40
|
+
):
|
|
41
|
+
count = len(output_files)
|
|
42
|
+
details = ", ".join([f"{i}" for i in output_files])
|
|
43
|
+
self.message_user(
|
|
44
|
+
request,
|
|
45
|
+
ngettext(
|
|
46
|
+
f"%d {message_singular} [{details}].",
|
|
47
|
+
f"%d {message_plural} [{details}].",
|
|
48
|
+
count,
|
|
49
|
+
)
|
|
50
|
+
% count,
|
|
51
|
+
message_type,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
@admin.action(description="Synchronize data from Galaxy")
|
|
55
|
+
def synchronize_file(self, request, queryset):
|
|
56
|
+
sync_output_files = []
|
|
57
|
+
error_output_files = []
|
|
58
|
+
for output_file in queryset:
|
|
59
|
+
try:
|
|
60
|
+
output_file.synchronize()
|
|
61
|
+
sync_output_files.append(output_file)
|
|
62
|
+
except: # noqa
|
|
63
|
+
error_output_files.append(output_file)
|
|
64
|
+
if sync_output_files:
|
|
65
|
+
self._get_message_output_file_synchronize(
|
|
66
|
+
request,
|
|
67
|
+
sync_output_files,
|
|
68
|
+
"output_file was successfully synchronized",
|
|
69
|
+
"output_files were successfully synchronized",
|
|
70
|
+
messages.SUCCESS,
|
|
71
|
+
)
|
|
72
|
+
if error_output_files:
|
|
73
|
+
self._get_message_output_file_synchronize(
|
|
74
|
+
request,
|
|
75
|
+
error_output_files,
|
|
76
|
+
"output_file could not be synchronized",
|
|
77
|
+
"output_files could not be synchronized",
|
|
78
|
+
messages.ERROR,
|
|
79
|
+
)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin, messages
|
|
4
|
+
from django.http import HttpResponseRedirect
|
|
5
|
+
from django.shortcuts import render
|
|
6
|
+
from django.urls import reverse
|
|
7
|
+
from django.utils.html import format_html
|
|
8
|
+
from django.utils.http import urlencode
|
|
9
|
+
from django.utils.translation import ngettext
|
|
10
|
+
|
|
11
|
+
from django_to_galaxy.models.galaxy_user import GalaxyUser
|
|
12
|
+
from django_to_galaxy.models.galaxy_element import Tag
|
|
13
|
+
from django_to_galaxy.admin.utils import update_workflowinputs
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@admin.register(GalaxyUser)
|
|
17
|
+
class GalaxyUserAdmin(admin.ModelAdmin):
|
|
18
|
+
list_display = (
|
|
19
|
+
"id",
|
|
20
|
+
"email",
|
|
21
|
+
"hide_api_key",
|
|
22
|
+
"galaxy_instance",
|
|
23
|
+
"get_number_histories",
|
|
24
|
+
"get_number_workflows",
|
|
25
|
+
)
|
|
26
|
+
list_filter = ("galaxy_instance",)
|
|
27
|
+
actions = ["create_history", "import_workflows"]
|
|
28
|
+
|
|
29
|
+
def get_urls(self):
|
|
30
|
+
from django.urls import path
|
|
31
|
+
|
|
32
|
+
return [
|
|
33
|
+
path(
|
|
34
|
+
"<path:object_id>/import_workflows/",
|
|
35
|
+
self._import_workflows_view,
|
|
36
|
+
name="Import workflow",
|
|
37
|
+
),
|
|
38
|
+
] + super().get_urls()
|
|
39
|
+
|
|
40
|
+
def hide_api_key(self, obj):
|
|
41
|
+
api_key = obj.api_key
|
|
42
|
+
return api_key.replace(api_key[4:-4], len(api_key[4:-4]) * "*")
|
|
43
|
+
|
|
44
|
+
def get_number_histories(self, obj):
|
|
45
|
+
count = obj.histories.count()
|
|
46
|
+
url = (
|
|
47
|
+
reverse("admin:django_to_galaxy_history_changelist")
|
|
48
|
+
+ "?"
|
|
49
|
+
+ urlencode({"galaxy_owner__id": f"{obj.id}"})
|
|
50
|
+
)
|
|
51
|
+
return format_html('<a href="{}">{}</a>', url, count)
|
|
52
|
+
|
|
53
|
+
def get_number_workflows(self, obj):
|
|
54
|
+
count = obj.workflows.count()
|
|
55
|
+
url = (
|
|
56
|
+
reverse("admin:django_to_galaxy_workflow_changelist")
|
|
57
|
+
+ "?"
|
|
58
|
+
+ urlencode({"galaxy_owner__id": f"{obj.id}"})
|
|
59
|
+
)
|
|
60
|
+
return format_html('<a href="{}">{}</a>', url, count)
|
|
61
|
+
|
|
62
|
+
def _get_message_history_creation(
|
|
63
|
+
self,
|
|
64
|
+
request,
|
|
65
|
+
users: List[GalaxyUser],
|
|
66
|
+
message_singular: str,
|
|
67
|
+
message_plural: str,
|
|
68
|
+
message_type: int,
|
|
69
|
+
):
|
|
70
|
+
count = len(users)
|
|
71
|
+
details = ", ".join([f"{u.email}->{u.galaxy_instance.url}" for u in users])
|
|
72
|
+
self.message_user(
|
|
73
|
+
request,
|
|
74
|
+
ngettext(
|
|
75
|
+
f"%d {message_singular} ({details}).",
|
|
76
|
+
f"%d {message_plural} ({details}).",
|
|
77
|
+
count,
|
|
78
|
+
)
|
|
79
|
+
% count,
|
|
80
|
+
message_type,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@admin.action(description="Create history")
|
|
84
|
+
def create_history(self, request, queryset):
|
|
85
|
+
created_users = []
|
|
86
|
+
skipped_users = []
|
|
87
|
+
for user in queryset:
|
|
88
|
+
try:
|
|
89
|
+
user.create_history()
|
|
90
|
+
created_users.append(user)
|
|
91
|
+
except: # noqa
|
|
92
|
+
skipped_users.append(user)
|
|
93
|
+
if created_users:
|
|
94
|
+
self._get_message_history_creation(
|
|
95
|
+
request,
|
|
96
|
+
created_users,
|
|
97
|
+
"history was successfully created",
|
|
98
|
+
"histories were successfully created",
|
|
99
|
+
messages.SUCCESS,
|
|
100
|
+
)
|
|
101
|
+
if skipped_users:
|
|
102
|
+
self._get_message_history_creation(
|
|
103
|
+
request,
|
|
104
|
+
skipped_users,
|
|
105
|
+
"history could not be created",
|
|
106
|
+
"histories could not be created",
|
|
107
|
+
messages.ERROR,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@admin.action(description="Import workflow(s) (1 user only)")
|
|
111
|
+
def import_workflows(self, request, queryset):
|
|
112
|
+
if queryset.count() > 1:
|
|
113
|
+
self.message_user(
|
|
114
|
+
request,
|
|
115
|
+
"You can import workflow from 1 user only at a time.",
|
|
116
|
+
messages.ERROR,
|
|
117
|
+
)
|
|
118
|
+
return
|
|
119
|
+
user = queryset[0]
|
|
120
|
+
if not user.galaxy_instance.is_online():
|
|
121
|
+
self.message_user(
|
|
122
|
+
request,
|
|
123
|
+
(
|
|
124
|
+
f"{user.galaxy_instance} is currently not available."
|
|
125
|
+
" Please try later or contact its administrator(s)."
|
|
126
|
+
),
|
|
127
|
+
messages.ERROR,
|
|
128
|
+
)
|
|
129
|
+
return None
|
|
130
|
+
return HttpResponseRedirect(f"{user.id}/import_workflows/")
|
|
131
|
+
|
|
132
|
+
def _import_workflows_view(self, request, object_id):
|
|
133
|
+
galaxy_user = GalaxyUser.objects.prefetch_related("workflows").get(id=object_id)
|
|
134
|
+
existing_workflows = list(galaxy_user.workflows.all())
|
|
135
|
+
existing_galaxy_ids = tuple(wf.galaxy_id for wf in existing_workflows)
|
|
136
|
+
new_workflows = []
|
|
137
|
+
for galaxy_wf, tags in galaxy_user.available_workflows:
|
|
138
|
+
if galaxy_wf.galaxy_id not in existing_galaxy_ids:
|
|
139
|
+
new_workflows.append((galaxy_wf, tags))
|
|
140
|
+
if request.method == "POST":
|
|
141
|
+
galaxy_id_to_save = tuple(request.POST.getlist("save_to_app"))
|
|
142
|
+
for wf, tags in new_workflows:
|
|
143
|
+
id_tags = []
|
|
144
|
+
for tag in tags:
|
|
145
|
+
savedtag, created = Tag.objects.get_or_create(label=tag)
|
|
146
|
+
id_tags.append(savedtag.id)
|
|
147
|
+
if wf.galaxy_id in galaxy_id_to_save:
|
|
148
|
+
wf.save()
|
|
149
|
+
try:
|
|
150
|
+
update_workflowinputs(wf.id)
|
|
151
|
+
except Exception as e:
|
|
152
|
+
self.message_user(
|
|
153
|
+
request,
|
|
154
|
+
f"Could not import '{wf.name}' workflow: {e}",
|
|
155
|
+
messages.ERROR,
|
|
156
|
+
)
|
|
157
|
+
else:
|
|
158
|
+
for tag in id_tags:
|
|
159
|
+
wf.tags.add(tag)
|
|
160
|
+
wf.save()
|
|
161
|
+
existing_workflows.append(wf)
|
|
162
|
+
new_workflows.remove((wf, tags))
|
|
163
|
+
self.message_user(
|
|
164
|
+
request,
|
|
165
|
+
f"Successfully imported '{wf.name}' workflow",
|
|
166
|
+
messages.SUCCESS,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
context = dict(
|
|
170
|
+
self.admin_site.each_context(request),
|
|
171
|
+
galaxy_user=galaxy_user,
|
|
172
|
+
existing_workflows=existing_workflows,
|
|
173
|
+
new_workflows=new_workflows,
|
|
174
|
+
)
|
|
175
|
+
return render(
|
|
176
|
+
request,
|
|
177
|
+
"admin/import_workflows.html",
|
|
178
|
+
context=context,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
hide_api_key.short_description = "API Key"
|
|
182
|
+
get_number_histories.short_description = "Histories"
|
|
183
|
+
get_number_workflows.short_description = "Workflows"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin, messages
|
|
4
|
+
from django.utils.translation import ngettext
|
|
5
|
+
|
|
6
|
+
from django_to_galaxy.models.history import History
|
|
7
|
+
|
|
8
|
+
from .galaxy_element import GalaxyElementAdmin
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@admin.register(History)
|
|
12
|
+
class HistoryAdmin(GalaxyElementAdmin):
|
|
13
|
+
list_display = (
|
|
14
|
+
"id",
|
|
15
|
+
"name",
|
|
16
|
+
"annotation",
|
|
17
|
+
"galaxy_id",
|
|
18
|
+
"published",
|
|
19
|
+
"galaxy_owner",
|
|
20
|
+
"tags",
|
|
21
|
+
"galaxy_state",
|
|
22
|
+
"create_time",
|
|
23
|
+
)
|
|
24
|
+
readonly_fields = (
|
|
25
|
+
"id",
|
|
26
|
+
"name",
|
|
27
|
+
"annotation",
|
|
28
|
+
"galaxy_id",
|
|
29
|
+
"published",
|
|
30
|
+
"galaxy_owner",
|
|
31
|
+
"tags",
|
|
32
|
+
"galaxy_state",
|
|
33
|
+
"create_time",
|
|
34
|
+
)
|
|
35
|
+
actions = ["synchronize_history"]
|
|
36
|
+
|
|
37
|
+
def tags(self, obj):
|
|
38
|
+
return ", ".join([p.label for p in obj.tags.all()])
|
|
39
|
+
|
|
40
|
+
def delete_queryset(self, request, queryset):
|
|
41
|
+
"""Might be slow when dealing with lot of items."""
|
|
42
|
+
for item in queryset:
|
|
43
|
+
item.delete()
|
|
44
|
+
|
|
45
|
+
def _get_message_history_synchronize(
|
|
46
|
+
self,
|
|
47
|
+
request,
|
|
48
|
+
histories: List[History],
|
|
49
|
+
message_singular: str,
|
|
50
|
+
message_plural: str,
|
|
51
|
+
message_type: int,
|
|
52
|
+
):
|
|
53
|
+
count = len(histories)
|
|
54
|
+
details = ", ".join([f"{h.galaxy_id} from {h.galaxy_owner}" for h in histories])
|
|
55
|
+
self.message_user(
|
|
56
|
+
request,
|
|
57
|
+
ngettext(
|
|
58
|
+
f"%d {message_singular} [{details}].",
|
|
59
|
+
f"%d {message_plural} [{details}].",
|
|
60
|
+
count,
|
|
61
|
+
)
|
|
62
|
+
% count,
|
|
63
|
+
message_type,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@admin.action(description="Synchronize data from Galaxy")
|
|
67
|
+
def synchronize_history(self, request, queryset):
|
|
68
|
+
sync_histories = []
|
|
69
|
+
error_histories = []
|
|
70
|
+
for history in queryset:
|
|
71
|
+
try:
|
|
72
|
+
history.synchronize()
|
|
73
|
+
sync_histories.append(history)
|
|
74
|
+
except: # noqa
|
|
75
|
+
error_histories.append(history)
|
|
76
|
+
if sync_histories:
|
|
77
|
+
self._get_message_history_synchronize(
|
|
78
|
+
request,
|
|
79
|
+
sync_histories,
|
|
80
|
+
"history was successfully synchronized",
|
|
81
|
+
"histories were successfully synchronized",
|
|
82
|
+
messages.SUCCESS,
|
|
83
|
+
)
|
|
84
|
+
if error_histories:
|
|
85
|
+
self._get_message_history_synchronize(
|
|
86
|
+
request,
|
|
87
|
+
error_histories,
|
|
88
|
+
"history could not be synchronized",
|
|
89
|
+
"histories could not be synchronized",
|
|
90
|
+
messages.ERROR,
|
|
91
|
+
)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin, messages
|
|
4
|
+
from django.utils.translation import ngettext
|
|
5
|
+
from django.utils.html import format_html
|
|
6
|
+
from django.utils.http import urlencode
|
|
7
|
+
from django.urls import reverse
|
|
8
|
+
|
|
9
|
+
from django_to_galaxy.models.invocation import Invocation
|
|
10
|
+
|
|
11
|
+
from .galaxy_element import GalaxyElementAdmin
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@admin.register(Invocation)
|
|
15
|
+
class InvocationAdmin(GalaxyElementAdmin):
|
|
16
|
+
list_display = (
|
|
17
|
+
"id",
|
|
18
|
+
"galaxy_id",
|
|
19
|
+
"display_percentage_done",
|
|
20
|
+
"status",
|
|
21
|
+
"workflow",
|
|
22
|
+
"history",
|
|
23
|
+
"create_time",
|
|
24
|
+
"get_number_output_files",
|
|
25
|
+
)
|
|
26
|
+
readonly_fields = (
|
|
27
|
+
"id",
|
|
28
|
+
"galaxy_id",
|
|
29
|
+
"display_percentage_done",
|
|
30
|
+
"status",
|
|
31
|
+
"workflow",
|
|
32
|
+
"history",
|
|
33
|
+
"create_time",
|
|
34
|
+
)
|
|
35
|
+
actions = ["synchronize_invocation", "update_output_files"]
|
|
36
|
+
|
|
37
|
+
@admin.display(description="Percentage Done")
|
|
38
|
+
def display_percentage_done(self, obj):
|
|
39
|
+
return format_html(
|
|
40
|
+
"""
|
|
41
|
+
<progress value="{0}" max="100"></progress>
|
|
42
|
+
<span style="font-weight:bold">{0}%</span>
|
|
43
|
+
""",
|
|
44
|
+
obj.percentage_done,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def _get_message_invocation(
|
|
48
|
+
self,
|
|
49
|
+
request,
|
|
50
|
+
invocations: List[Invocation],
|
|
51
|
+
message_singular: str,
|
|
52
|
+
message_plural: str,
|
|
53
|
+
message_type: int,
|
|
54
|
+
):
|
|
55
|
+
count = len(invocations)
|
|
56
|
+
details = ", ".join([f"{i}" for i in invocations])
|
|
57
|
+
self.message_user(
|
|
58
|
+
request,
|
|
59
|
+
ngettext(
|
|
60
|
+
f"%d {message_singular} [{details}].",
|
|
61
|
+
f"%d {message_plural} [{details}].",
|
|
62
|
+
count,
|
|
63
|
+
)
|
|
64
|
+
% count,
|
|
65
|
+
message_type,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def _get_message_output_files(
|
|
69
|
+
self,
|
|
70
|
+
request,
|
|
71
|
+
invocations: List[Invocation],
|
|
72
|
+
message_singular: str,
|
|
73
|
+
message_plural: str,
|
|
74
|
+
message_type: int,
|
|
75
|
+
):
|
|
76
|
+
count = 0
|
|
77
|
+
for inv in invocations:
|
|
78
|
+
count += inv.output_files.count()
|
|
79
|
+
details = ", ".join([f"{i}" for i in invocations])
|
|
80
|
+
self.message_user(
|
|
81
|
+
request,
|
|
82
|
+
ngettext(
|
|
83
|
+
f"%d {message_singular} [{details}].",
|
|
84
|
+
f"%d {message_plural} [{details}].",
|
|
85
|
+
count,
|
|
86
|
+
)
|
|
87
|
+
% count,
|
|
88
|
+
message_type,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
@admin.action(description="Synchronize data from Galaxy")
|
|
92
|
+
def synchronize_invocation(self, request, queryset):
|
|
93
|
+
sync_invocations = []
|
|
94
|
+
error_invocations = []
|
|
95
|
+
for invocation in queryset:
|
|
96
|
+
try:
|
|
97
|
+
invocation.synchronize()
|
|
98
|
+
sync_invocations.append(invocation)
|
|
99
|
+
except: # noqa
|
|
100
|
+
error_invocations.append(invocation)
|
|
101
|
+
if sync_invocations:
|
|
102
|
+
self._get_message_invocation(
|
|
103
|
+
request,
|
|
104
|
+
sync_invocations,
|
|
105
|
+
"invocation was successfully synchronized",
|
|
106
|
+
"invocations were successfully synchronized",
|
|
107
|
+
messages.SUCCESS,
|
|
108
|
+
)
|
|
109
|
+
if error_invocations:
|
|
110
|
+
self._get_message_invocation(
|
|
111
|
+
request,
|
|
112
|
+
error_invocations,
|
|
113
|
+
"invocation could not be synchronized",
|
|
114
|
+
"invocations could not be synchronized",
|
|
115
|
+
messages.ERROR,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@admin.action(description="Update Output files")
|
|
119
|
+
def update_output_files(self, request, queryset):
|
|
120
|
+
updated_invocations = []
|
|
121
|
+
error_invocations = []
|
|
122
|
+
for invocation in queryset:
|
|
123
|
+
try:
|
|
124
|
+
invocation.update_output_files()
|
|
125
|
+
updated_invocations.append(invocation)
|
|
126
|
+
except: # noqa
|
|
127
|
+
error_invocations.append(invocation)
|
|
128
|
+
if updated_invocations:
|
|
129
|
+
self._get_message_output_files(
|
|
130
|
+
request,
|
|
131
|
+
updated_invocations,
|
|
132
|
+
"output file from invocation(s) were successfully updated",
|
|
133
|
+
"output files from invocation(s) were successfully updated",
|
|
134
|
+
messages.SUCCESS,
|
|
135
|
+
)
|
|
136
|
+
if error_invocations:
|
|
137
|
+
self._get_message_output_files(
|
|
138
|
+
request,
|
|
139
|
+
error_invocations,
|
|
140
|
+
"output file from invocation(s) could not be updated",
|
|
141
|
+
"output files from invocation(s) could not be updated",
|
|
142
|
+
messages.ERROR,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def get_number_output_files(self, obj):
|
|
146
|
+
count = obj.output_files.count()
|
|
147
|
+
url = (
|
|
148
|
+
reverse("admin:django_to_galaxy_galaxyoutputfile_changelist")
|
|
149
|
+
+ "?"
|
|
150
|
+
+ urlencode({"invocation__id": f"{obj.id}"})
|
|
151
|
+
)
|
|
152
|
+
return format_html('<a href="{}">{}</a>', url, count)
|
|
153
|
+
|
|
154
|
+
get_number_output_files.short_description = "Output files"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
from django_to_galaxy.models.galaxy_element import Tag
|
|
4
|
+
|
|
5
|
+
from .galaxy_element import GalaxyElementAdmin
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@admin.register(Tag)
|
|
9
|
+
class TagAdmin(GalaxyElementAdmin):
|
|
10
|
+
list_display = (
|
|
11
|
+
"id",
|
|
12
|
+
"label",
|
|
13
|
+
)
|
|
14
|
+
readonly_fields = (
|
|
15
|
+
"id",
|
|
16
|
+
"label",
|
|
17
|
+
)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from django_to_galaxy.models.workflow import Workflow
|
|
2
|
+
from django.db import transaction
|
|
3
|
+
from django_to_galaxy.models.accepted_input import (
|
|
4
|
+
Format,
|
|
5
|
+
WorkflowInput,
|
|
6
|
+
DATA,
|
|
7
|
+
COLLECTION,
|
|
8
|
+
PARAMETER,
|
|
9
|
+
P_TEXT,
|
|
10
|
+
WorkflowInputTextOption,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
Update inputs information of a workflow functions
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def search_step_info_value(key, value_none, step_info):
|
|
19
|
+
if key in step_info["tool_inputs"].keys():
|
|
20
|
+
value = step_info["tool_inputs"][key]
|
|
21
|
+
else:
|
|
22
|
+
try:
|
|
23
|
+
value = step_info["target_tools"][0]["tool_input"][key]
|
|
24
|
+
except Exception:
|
|
25
|
+
value = value_none
|
|
26
|
+
|
|
27
|
+
return value
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def update_workflowinputs(workflow_id):
|
|
31
|
+
wf = Workflow.objects.get(id=workflow_id)
|
|
32
|
+
try:
|
|
33
|
+
with transaction.atomic():
|
|
34
|
+
# Saving workflow inputs
|
|
35
|
+
input_mapping = wf.get_workflow_inputs()
|
|
36
|
+
|
|
37
|
+
# Remove existing inputs
|
|
38
|
+
WorkflowInput.objects.filter(workflow=wf).delete()
|
|
39
|
+
|
|
40
|
+
for step, step_info in input_mapping.items():
|
|
41
|
+
input_type = step_info["type"]
|
|
42
|
+
if input_type == DATA:
|
|
43
|
+
workflowinput, created = WorkflowInput.objects.get_or_create(
|
|
44
|
+
galaxy_step_id=step,
|
|
45
|
+
label=step_info["label"],
|
|
46
|
+
workflow=wf,
|
|
47
|
+
input_type=input_type,
|
|
48
|
+
parameter_type=None,
|
|
49
|
+
collection_type=None,
|
|
50
|
+
optional=step_info["tool_inputs"]["optional"],
|
|
51
|
+
default_value=None,
|
|
52
|
+
multiple=False,
|
|
53
|
+
)
|
|
54
|
+
elif input_type == COLLECTION:
|
|
55
|
+
workflowinput, created = WorkflowInput.objects.get_or_create(
|
|
56
|
+
galaxy_step_id=step,
|
|
57
|
+
label=step_info["label"],
|
|
58
|
+
workflow=wf,
|
|
59
|
+
input_type=input_type,
|
|
60
|
+
parameter_type=None,
|
|
61
|
+
collection_type=step_info["tool_inputs"]["collection_type"],
|
|
62
|
+
optional=step_info["tool_inputs"]["optional"],
|
|
63
|
+
default_value=None,
|
|
64
|
+
multiple=False,
|
|
65
|
+
)
|
|
66
|
+
elif input_type == PARAMETER:
|
|
67
|
+
parameter_type = step_info["tool_inputs"]["parameter_type"]
|
|
68
|
+
default_value = search_step_info_value("default", None, step_info)
|
|
69
|
+
multiple = search_step_info_value("multiple", False, step_info)
|
|
70
|
+
|
|
71
|
+
workflowinput, created = WorkflowInput.objects.get_or_create(
|
|
72
|
+
galaxy_step_id=step,
|
|
73
|
+
label=step_info["label"],
|
|
74
|
+
workflow=wf,
|
|
75
|
+
input_type=input_type,
|
|
76
|
+
parameter_type=parameter_type,
|
|
77
|
+
collection_type=None,
|
|
78
|
+
optional=step_info["tool_inputs"]["optional"],
|
|
79
|
+
default_value=default_value,
|
|
80
|
+
multiple=multiple,
|
|
81
|
+
)
|
|
82
|
+
if created and parameter_type == P_TEXT:
|
|
83
|
+
# Add TextOption
|
|
84
|
+
if "restrictions" in step_info["tool_inputs"].keys():
|
|
85
|
+
# If there are restrictions, we're saving them
|
|
86
|
+
for value in step_info["tool_inputs"]["restrictions"]:
|
|
87
|
+
(
|
|
88
|
+
workflowinputtextoption,
|
|
89
|
+
_,
|
|
90
|
+
) = WorkflowInputTextOption.objects.get_or_create(
|
|
91
|
+
workflow_input=workflowinput, text_option=value
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
# If no restrictions, we are getting the options from the 1st tool
|
|
95
|
+
try:
|
|
96
|
+
tool_info = step_info["target_tools"][0]
|
|
97
|
+
for opt in tool_info["tool_input"]["options"]:
|
|
98
|
+
(
|
|
99
|
+
workflowinputtextoption,
|
|
100
|
+
_,
|
|
101
|
+
) = WorkflowInputTextOption.objects.get_or_create(
|
|
102
|
+
workflow_input=workflowinput, text_option=opt[1]
|
|
103
|
+
)
|
|
104
|
+
except (KeyError, ValueError):
|
|
105
|
+
pass
|
|
106
|
+
if "format" in step_info["tool_inputs"].keys():
|
|
107
|
+
for format in step_info["tool_inputs"]["format"]:
|
|
108
|
+
(
|
|
109
|
+
winputformat,
|
|
110
|
+
_,
|
|
111
|
+
) = Format.objects.get_or_create(format=format.strip())
|
|
112
|
+
workflowinput.formats.add(winputformat.id)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
raise e
|
|
115
|
+
else:
|
|
116
|
+
return
|