|
a |
|
b/qiita_pet/util.py |
|
|
1 |
r""" |
|
|
2 |
Util functions (:mod: `qiita_pet.util`) |
|
|
3 |
====================================== |
|
|
4 |
|
|
|
5 |
..currentmodule:: qiita_pet.util |
|
|
6 |
|
|
|
7 |
This module provides different util functions for qiita_pet. |
|
|
8 |
|
|
|
9 |
Methods |
|
|
10 |
------- |
|
|
11 |
|
|
|
12 |
..autosummary:: |
|
|
13 |
:toctree: generated/ |
|
|
14 |
|
|
|
15 |
clean_str |
|
|
16 |
""" |
|
|
17 |
# ----------------------------------------------------------------------------- |
|
|
18 |
# Copyright (c) 2014--, The Qiita Development Team. |
|
|
19 |
# |
|
|
20 |
# Distributed under the terms of the BSD 3-clause License. |
|
|
21 |
# |
|
|
22 |
# The full license is in the file LICENSE, distributed with this software. |
|
|
23 |
# ----------------------------------------------------------------------------- |
|
|
24 |
from tornado.escape import linkify as tornado_linkify, xhtml_unescape |
|
|
25 |
|
|
|
26 |
from qiita_core.util import execute_as_transaction |
|
|
27 |
from qiita_db.reference import Reference |
|
|
28 |
|
|
|
29 |
|
|
|
30 |
STATUS_STYLER = { |
|
|
31 |
'sandbox': |
|
|
32 |
('glyphicon glyphicon-eye-close', 'glyphicon glyphicon-lock', 'gray'), |
|
|
33 |
'awaiting_approval': |
|
|
34 |
('glyphicon glyphicon-eye-open', 'glyphicon glyphicon-lock', 'peru'), |
|
|
35 |
'private': |
|
|
36 |
('glyphicon glyphicon-eye-open', 'glyphicon glyphicon-lock', |
|
|
37 |
'#3599FD'), |
|
|
38 |
'public': |
|
|
39 |
('glyphicon glyphicon-eye-open', 'glyphicon glyphicon-globe', 'green')} |
|
|
40 |
|
|
|
41 |
EBI_LINKIFIER = ('<a href="http://www.ebi.ac.uk/ena/data/view/{0}" ' |
|
|
42 |
'target="_blank">{0}</a>') |
|
|
43 |
|
|
|
44 |
|
|
|
45 |
def linkify(link_template, item): |
|
|
46 |
"""Formats a strings into a URL using string replacement |
|
|
47 |
|
|
|
48 |
Paramters |
|
|
49 |
--------- |
|
|
50 |
link_template : str |
|
|
51 |
The template for the URL. |
|
|
52 |
item : list or tuple of str |
|
|
53 |
The strings that will be inserted into the template |
|
|
54 |
""" |
|
|
55 |
return link_template.format(*item) |
|
|
56 |
|
|
|
57 |
|
|
|
58 |
def clean_str(item): |
|
|
59 |
"""Converts input to string and replaces spaces with underscores |
|
|
60 |
|
|
|
61 |
Parameters |
|
|
62 |
---------- |
|
|
63 |
item : anything convertable to string |
|
|
64 |
item to convert and clean |
|
|
65 |
|
|
|
66 |
Returns |
|
|
67 |
------- |
|
|
68 |
str |
|
|
69 |
cleaned string |
|
|
70 |
""" |
|
|
71 |
return str(item).replace(" ", "_").replace(":", "") |
|
|
72 |
|
|
|
73 |
|
|
|
74 |
def convert_text_html(message): |
|
|
75 |
"""Linkify URLs and turn newlines into <br/> for HTML""" |
|
|
76 |
html = xhtml_unescape(tornado_linkify(message)) |
|
|
77 |
return html.replace('\n', '<br/>') |
|
|
78 |
|
|
|
79 |
|
|
|
80 |
@execute_as_transaction |
|
|
81 |
def generate_param_str(param): |
|
|
82 |
"""Generate an html string with the parameter values |
|
|
83 |
|
|
|
84 |
Parameters |
|
|
85 |
---------- |
|
|
86 |
param : BaseParameters |
|
|
87 |
The parameter to generate the str |
|
|
88 |
|
|
|
89 |
Returns |
|
|
90 |
------- |
|
|
91 |
str |
|
|
92 |
The html string with the parameter set values |
|
|
93 |
""" |
|
|
94 |
values = param.values |
|
|
95 |
ref = Reference(values['reference']) |
|
|
96 |
result = ["<b>Reference:</b> %s %s" % (ref.name, ref.version)] |
|
|
97 |
result.extend("<b>%s:</b> %s" % (name, value) |
|
|
98 |
for name, value in values.items() |
|
|
99 |
if name != 'reference') |
|
|
100 |
return "<br/>".join(result) |
|
|
101 |
|
|
|
102 |
|
|
|
103 |
def is_localhost(host): |
|
|
104 |
"""Verifies if the connection is local |
|
|
105 |
|
|
|
106 |
Parameters |
|
|
107 |
---------- |
|
|
108 |
host : str |
|
|
109 |
The requesting host, in general self.request.headers['host'] |
|
|
110 |
|
|
|
111 |
Returns |
|
|
112 |
------- |
|
|
113 |
bool |
|
|
114 |
True if local request |
|
|
115 |
""" |
|
|
116 |
localhost = ('localhost', '127.0.0.1') |
|
|
117 |
return host.startswith(localhost) |
|
|
118 |
|
|
|
119 |
|
|
|
120 |
def get_artifact_processing_status(artifact): |
|
|
121 |
"""Gets the processing status of the artifact |
|
|
122 |
|
|
|
123 |
Parameters |
|
|
124 |
---------- |
|
|
125 |
artifact : qiita_db.artifact.Artifact |
|
|
126 |
The artifact to get the processing status |
|
|
127 |
|
|
|
128 |
Returns |
|
|
129 |
------- |
|
|
130 |
str, str |
|
|
131 |
The processing status {'processing', 'failed', 'success', |
|
|
132 |
'Not processed'} |
|
|
133 |
A summary of the jobs attached to the artifact |
|
|
134 |
""" |
|
|
135 |
preprocessing_status = 'Not processed' |
|
|
136 |
preprocessing_status_msg = [] |
|
|
137 |
for job in artifact.jobs(): |
|
|
138 |
job_status = job.status |
|
|
139 |
if job_status == 'error': |
|
|
140 |
if preprocessing_status != 'success': |
|
|
141 |
preprocessing_status = 'failed' |
|
|
142 |
preprocessing_status_msg.append( |
|
|
143 |
"<b>Job %s</b>: failed - %s" |
|
|
144 |
% (job.id, job.log.msg)) |
|
|
145 |
elif job_status == 'success': |
|
|
146 |
preprocessing_status = 'success' |
|
|
147 |
else: |
|
|
148 |
if preprocessing_status != 'success': |
|
|
149 |
preprocessing_status = 'processing' |
|
|
150 |
preprocessing_status_msg.append( |
|
|
151 |
"<b>Job %s</b>: %s" % (job.id, job_status)) |
|
|
152 |
|
|
|
153 |
if not preprocessing_status_msg: |
|
|
154 |
preprocessing_status_msg = 'Not processed' |
|
|
155 |
else: |
|
|
156 |
preprocessing_status_msg = convert_text_html( |
|
|
157 |
'<br/>'.join(preprocessing_status_msg)) |
|
|
158 |
|
|
|
159 |
return preprocessing_status, preprocessing_status_msg |
|
|
160 |
|
|
|
161 |
|
|
|
162 |
def get_network_nodes_edges(graph, full_access, nodes=None, edges=None): |
|
|
163 |
"""Returns the JavaScript friendly representation of the graph |
|
|
164 |
|
|
|
165 |
Parameters |
|
|
166 |
---------- |
|
|
167 |
graph : networkx.DiGraph |
|
|
168 |
The artifact/jobs graph |
|
|
169 |
full_access : bool |
|
|
170 |
Whether the user has full access to the graph or not |
|
|
171 |
nodes : list, optional |
|
|
172 |
A pre-populated list of nodes. Useful for the analysis pipeline |
|
|
173 |
edges : list, optional |
|
|
174 |
A pre-populated list of edges. Useful for the analysis pipeline |
|
|
175 |
|
|
|
176 |
Returns |
|
|
177 |
------- |
|
|
178 |
(list, list, int) |
|
|
179 |
The list of nodes, the list of edges, and the worklfow id if there is |
|
|
180 |
any job on construction |
|
|
181 |
""" |
|
|
182 |
nodes = nodes if nodes is not None else [] |
|
|
183 |
edges = edges if edges is not None else [] |
|
|
184 |
workflow_id = None |
|
|
185 |
|
|
|
186 |
# n[0] is the data type: job/artifact/type |
|
|
187 |
# n[1] is the object |
|
|
188 |
for n in graph.nodes(): |
|
|
189 |
if n[0] == 'job': |
|
|
190 |
# ignoring internal Jobs |
|
|
191 |
if n[1].command.software.name == 'Qiita': |
|
|
192 |
continue |
|
|
193 |
atype = 'job' |
|
|
194 |
name = n[1].command.name |
|
|
195 |
status = n[1].status |
|
|
196 |
wkflow = n[1].processing_job_workflow |
|
|
197 |
if status == 'in_construction' and wkflow is not None: |
|
|
198 |
workflow_id = wkflow.id |
|
|
199 |
elif n[0] == 'artifact': |
|
|
200 |
atype = n[1].artifact_type |
|
|
201 |
status = 'artifact' |
|
|
202 |
pp = n[1].processing_parameters |
|
|
203 |
if pp is not None: |
|
|
204 |
cmd = pp.command |
|
|
205 |
if cmd.software.deprecated: |
|
|
206 |
status = 'deprecated' |
|
|
207 |
elif not cmd.active: |
|
|
208 |
status = 'outdated' |
|
|
209 |
if full_access or n[1].visibility == 'public': |
|
|
210 |
name = '%s\n(%s)' % (n[1].name, n[1].artifact_type) |
|
|
211 |
else: |
|
|
212 |
continue |
|
|
213 |
elif n[0] == 'type': |
|
|
214 |
atype = n[1].type |
|
|
215 |
name = '%s\n(%s)' % (n[1].name, n[1].type) |
|
|
216 |
status = 'type' |
|
|
217 |
else: |
|
|
218 |
# this should never happen but let's add it just in case |
|
|
219 |
raise ValueError('not valid node type: %s' % n[0]) |
|
|
220 |
nodes.append((n[0], atype, n[1].id, name, status)) |
|
|
221 |
|
|
|
222 |
edges.extend([(n[1].id, m[1].id) for n, m in graph.edges()]) |
|
|
223 |
|
|
|
224 |
return nodes, edges, workflow_id |