Skip to content

Commit a7e3d8b

Browse files
josenavasantgonza
authored andcommitted
Expand html summary setter (#2150)
* Changing the HTML setter to add support dirs * Extending the patch operation * Fixing remaining calls to html_summary_fp set * Fixing test * Deleting unused function * Removing unused import * Fixing tests * Fixing failing test
1 parent 1c74b04 commit a7e3d8b

File tree

12 files changed

+126
-86
lines changed

12 files changed

+126
-86
lines changed

qiita_db/artifact.py

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
from itertools import chain
1212
from datetime import datetime
1313
from os import remove
14+
from os.path import isfile
15+
from shutil import rmtree
16+
from functools import partial
1417

1518
import networkx as nx
1619

@@ -941,41 +944,55 @@ def html_summary_fp(self):
941944

942945
return res
943946

944-
@html_summary_fp.setter
945-
def html_summary_fp(self, value):
947+
def set_html_summary(self, html_fp, support_dir=None):
946948
"""Sets the HTML summary of the artifact
947949
948950
Parameters
949951
----------
950-
value : str
952+
html_fp : str
951953
Path to the new HTML summary
954+
support_dir : str
955+
Path to the directory containing any support files needed by
956+
the HTML file
952957
"""
953958
with qdb.sql_connection.TRN:
954-
current = self.html_summary_fp
955-
if current:
959+
if self.html_summary_fp:
956960
# Delete the current HTML summary
957-
fp_id = current[0]
958-
fp = current[1]
961+
to_delete_ids = []
962+
to_delete_fps = []
963+
for fp_id, fp, fp_type in self.filepaths:
964+
if fp_type in ('html_summary', 'html_summary_dir'):
965+
to_delete_ids.append([fp_id])
966+
to_delete_fps.append(fp)
959967
# From the artifact_filepath table
960968
sql = """DELETE FROM qiita.artifact_filepath
961969
WHERE filepath_id = %s"""
962-
qdb.sql_connection.TRN.add(sql, [fp_id])
970+
qdb.sql_connection.TRN.add(sql, to_delete_ids, many=True)
963971
# From the filepath table
964972
sql = "DELETE FROM qiita.filepath WHERE filepath_id=%s"
965-
qdb.sql_connection.TRN.add(sql, [fp_id])
973+
qdb.sql_connection.TRN.add(sql, to_delete_ids, many=True)
966974
# And from the filesystem only after the transaction is
967975
# successfully completed (after commit)
968-
qdb.sql_connection.TRN.add_post_commit_func(remove, fp)
976+
977+
def path_cleaner(fp):
978+
if isfile(fp):
979+
remove(fp)
980+
else:
981+
rmtree(fp)
982+
qdb.sql_connection.TRN.add_post_commit_func(
983+
partial(map, path_cleaner, to_delete_fps))
969984

970985
# Add the new HTML summary
986+
filepaths = [(html_fp, 'html_summary')]
987+
if support_dir is not None:
988+
filepaths.append((support_dir, 'html_summary_dir'))
971989
fp_ids = qdb.util.insert_filepaths(
972-
[(value, 'html_summary')], self.id, self.artifact_type,
973-
"filepath")
990+
filepaths, self.id, self.artifact_type, "filepath")
974991
sql = """INSERT INTO qiita.artifact_filepath
975992
(artifact_id, filepath_id)
976993
VALUES (%s, %s)"""
977-
# We only inserted a single filepath, so using index 0
978-
qdb.sql_connection.TRN.add(sql, [self.id, fp_ids[0]])
994+
sql_args = [[self.id, id_] for id_ in fp_ids]
995+
qdb.sql_connection.TRN.add(sql, sql_args, many=True)
979996
qdb.sql_connection.TRN.execute()
980997

981998
@property

qiita_db/handlers/artifact.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,17 @@ def patch(self, artifact_id):
131131
raise HTTPError(400, 'Incorrect path parameter value')
132132
else:
133133
artifact = _get_artifact(artifact_id)
134+
135+
try:
136+
html_data = loads(req_value)
137+
html_fp = html_data['html']
138+
html_dir = html_data['dir']
139+
except ValueError:
140+
html_fp = req_value
141+
html_dir = None
142+
134143
try:
135-
artifact.html_summary_fp = req_value
144+
artifact.set_html_summary(html_fp, html_dir)
136145
except Exception as e:
137146
raise HTTPError(500, str(e))
138147
else:

qiita_db/handlers/tests/test_artifact.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
from unittest import main, TestCase
1010
from json import loads
1111
from functools import partial
12-
from os.path import join, exists
12+
from os.path import join, exists, isfile
1313
from os import close, remove
14-
from tempfile import mkstemp
14+
from shutil import rmtree
15+
from tempfile import mkstemp, mkdtemp
1516
from json import dumps
1617

1718
from tornado.web import HTTPError
@@ -39,15 +40,16 @@ class ArtifactHandlerTests(OauthTestingBase):
3940
def setUp(self):
4041
super(ArtifactHandlerTests, self).setUp()
4142

42-
fd, self.html_fp = mkstemp(suffix=".html")
43-
close(fd)
44-
self._clean_up_files = [self.html_fp]
43+
self._clean_up_files = []
4544

4645
def tearDown(self):
4746
super(ArtifactHandlerTests, self).tearDown()
4847
for fp in self._clean_up_files:
4948
if exists(fp):
50-
remove(fp)
49+
if isfile(fp):
50+
remove(fp)
51+
else:
52+
rmtree(fp)
5153

5254
def test_get_artifact_does_not_exist(self):
5355
obs = self.get('/qiita_db/artifacts/100/', headers=self.header)
@@ -110,18 +112,40 @@ def test_get_artifact(self):
110112
self.assertEqual(obs, exp)
111113

112114
def test_patch(self):
115+
fd, html_fp = mkstemp(suffix=".html")
116+
close(fd)
117+
self._clean_up_files.append(html_fp)
118+
# correct argument with a single HTML
119+
arguments = {'op': 'add', 'path': '/html_summary/',
120+
'value': html_fp}
121+
artifact = qdb.artifact.Artifact(1)
122+
self.assertIsNone(artifact.html_summary_fp)
123+
obs = self.patch('/qiita_db/artifacts/1/',
124+
headers=self.header,
125+
data=arguments)
126+
self.assertEqual(obs.code, 200)
127+
self.assertIsNotNone(artifact.html_summary_fp)
128+
129+
# Correct argument with an HMTL and a directory
130+
fd, html_fp = mkstemp(suffix=".html")
131+
close(fd)
132+
self._clean_up_files.append(html_fp)
133+
html_dir = mkdtemp()
134+
self._clean_up_files.append(html_dir)
113135
arguments = {'op': 'add', 'path': '/html_summary/',
114-
'value': self.html_fp}
115-
self.assertIsNone(qdb.artifact.Artifact(1).html_summary_fp)
136+
'value': dumps({'html': html_fp, 'dir': html_dir})}
116137
obs = self.patch('/qiita_db/artifacts/1/',
117138
headers=self.header,
118139
data=arguments)
119140
self.assertEqual(obs.code, 200)
120-
self.assertIsNotNone(qdb.artifact.Artifact(1).html_summary_fp)
141+
self.assertIsNotNone(artifact.html_summary_fp)
142+
html_dir = [fp for _, fp, fp_type in artifact.filepaths
143+
if fp_type == 'html_summary_dir']
144+
self.assertEqual(len(html_dir), 1)
121145

122146
# Wrong operation
123147
arguments = {'op': 'wrong', 'path': '/html_summary/',
124-
'value': self.html_fp}
148+
'value': html_fp}
125149
obs = self.patch('/qiita_db/artifacts/1/',
126150
headers=self.header,
127151
data=arguments)
@@ -131,7 +155,7 @@ def test_patch(self):
131155

132156
# Wrong path parameter
133157
arguments = {'op': 'add', 'path': '/wrong/',
134-
'value': self.html_fp}
158+
'value': html_fp}
135159
obs = self.patch('/qiita_db/artifacts/1/',
136160
headers=self.header,
137161
data=arguments)
@@ -140,7 +164,7 @@ def test_patch(self):
140164

141165
# Wrong value parameter
142166
arguments = {'op': 'add', 'path': '/html_summary/',
143-
'value': self.html_fp}
167+
'value': html_fp}
144168
obs = self.patch('/qiita_db/artifacts/1/',
145169
headers=self.header,
146170
data=arguments)

qiita_db/support_files/patches/54.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,7 @@ BEGIN
117117
INSERT INTO qiita.command_parameter (command_id, parameter_name, parameter_type, required, default_value)
118118
VALUES (baf_cmd_id, 'analysis', 'analysis', True, NULL),
119119
(baf_cmd_id, 'merge_dup_sample_ids', 'bool', False, 'False');
120-
END $do$
120+
END $do$;
121+
122+
-- Add a new filepath type
123+
INSERT INTO qiita.filepath_type (filepath_type) VALUES ('html_summary_dir');

qiita_db/test/test_artifact.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# -----------------------------------------------------------------------------
88

99
from unittest import TestCase, main
10-
from tempfile import mkstemp
10+
from tempfile import mkstemp, mkdtemp
1111
from datetime import datetime
1212
from os import close, remove
1313
from os.path import exists, join, basename
@@ -1129,20 +1129,41 @@ def test_html_summary_setter(self):
11291129
path_builder = partial(join, db_fastq_dir, str(a.id))
11301130

11311131
# Check the setter works when the artifact does not have the summary
1132-
a.html_summary_fp = fp
1132+
a.set_html_summary(fp)
11331133
exp1 = path_builder(basename(fp))
11341134
self.assertEqual(a.html_summary_fp[1], exp1)
11351135

11361136
fd, fp = mkstemp(suffix=".html")
11371137
close(fd)
11381138
self._clean_up_files.append(fp)
11391139

1140+
dp = mkdtemp()
1141+
self._clean_up_files.append(dp)
1142+
11401143
# Check the setter works when the artifact already has a summary
1141-
a.html_summary_fp = fp
1144+
# and with a directory
1145+
a.set_html_summary(fp, support_dir=dp)
11421146
exp2 = path_builder(basename(fp))
11431147
self.assertEqual(a.html_summary_fp[1], exp2)
11441148
self.assertFalse(exists(exp1))
11451149

1150+
# Check that the setter correctly removes the directory if a new
1151+
# summary is added. Magic number 0. There is only one html_summary_dir
1152+
# added on the previous test
1153+
old_dir_fp = [old_fp for _, old_fp, fptype in a.filepaths
1154+
if fptype == 'html_summary_dir'][0]
1155+
fd, fp = mkstemp(suffix='.html')
1156+
close(fd)
1157+
self._clean_up_files.append(fp)
1158+
a.set_html_summary(fp)
1159+
exp3 = path_builder(basename(fp))
1160+
self.assertEqual(a.html_summary_fp[1], exp3)
1161+
self.assertFalse(exists(exp2))
1162+
self.assertFalse(exists(old_dir_fp))
1163+
summary_dir = [old_fp for _, old_fp, fptype in a.filepaths
1164+
if fptype == 'html_summary_dir']
1165+
self.assertEqual(summary_dir, [])
1166+
11461167
def test_descendants_with_jobs_one_element(self):
11471168
artifact = qdb.artifact.Artifact.create(
11481169
self.filepaths_root, 'FASTQ', prep_template=self.prep_template)

qiita_db/test/test_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_filepath(self):
3939
self.assertEqual(get_count("qiita.filepath"), 25)
4040

4141
def test_filepath_type(self):
42-
self.assertEqual(get_count("qiita.filepath_type"), 21)
42+
self.assertEqual(get_count("qiita.filepath_type"), 22)
4343

4444
def test_study_prep_template(self):
4545
self.assertEqual(get_count("qiita.study_prep_template"), 2)

qiita_pet/handlers/api_proxy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
study_tags_request)
3131
from .artifact import (artifact_graph_get_req, artifact_types_get_req,
3232
artifact_post_req, artifact_get_req,
33-
artifact_status_put_req, artifact_delete_req,
33+
artifact_status_put_req,
3434
artifact_summary_get_request, artifact_get_prep_req,
3535
artifact_summary_post_request, artifact_patch_request)
3636
from .ontology import ontology_patch_handler
@@ -51,7 +51,7 @@
5151
'prep_template_delete_req', 'artifact_get_prep_req',
5252
'prep_template_graph_get_req', 'prep_template_filepaths_get_req',
5353
'artifact_get_req', 'artifact_status_put_req',
54-
'artifact_delete_req', 'prep_template_get_req', 'study_delete_req',
54+
'prep_template_get_req', 'study_delete_req',
5555
'study_prep_get_req', 'sample_template_get_req',
5656
'artifact_graph_get_req', 'artifact_types_get_req',
5757
'artifact_post_req',

qiita_pet/handlers/api_proxy/artifact.py

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from qiita_core.qiita_settings import qiita_config
1818
from qiita_pet.handlers.api_proxy.util import check_access, check_fp
1919
from qiita_ware.context import safe_submit
20-
from qiita_ware.dispatchable import (copy_raw_data, delete_artifact)
20+
from qiita_ware.dispatchable import copy_raw_data
2121
from qiita_db.artifact import Artifact
2222
from qiita_db.user import User
2323
from qiita_db.metadata_template.prep_template import PrepTemplate
@@ -506,37 +506,6 @@ def artifact_graph_get_req(artifact_id, direction, user_id):
506506
'message': ''}
507507

508508

509-
def artifact_delete_req(artifact_id, user_id):
510-
"""Deletes the artifact
511-
512-
Parameters
513-
----------
514-
artifact_id : int
515-
Artifact being acted on
516-
user_id : str
517-
The user requesting the action
518-
519-
Returns
520-
-------
521-
dict
522-
Status of action, in the form {'status': status, 'message': msg}
523-
status: status of the action, either success or error
524-
message: Human readable message for status
525-
"""
526-
pd = Artifact(int(artifact_id))
527-
pt_id = pd.prep_templates[0].id
528-
access_error = check_access(pd.study.id, user_id)
529-
if access_error:
530-
return access_error
531-
532-
job_id = safe_submit(user_id, delete_artifact, artifact_id)
533-
r_client.set(PREP_TEMPLATE_KEY_FORMAT % pt_id,
534-
dumps({'job_id': job_id, 'is_qiita_job': False}))
535-
536-
return {'status': 'success',
537-
'message': ''}
538-
539-
540509
def artifact_status_put_req(artifact_id, user_id, visibility):
541510
"""Set the status of the artifact given
542511

qiita_pet/handlers/api_proxy/tests/test_artifact.py

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from qiita_db.exceptions import QiitaDBWarning
2828
from qiita_pet.handlers.api_proxy.artifact import (
2929
artifact_get_req, artifact_status_put_req, artifact_graph_get_req,
30-
artifact_delete_req, artifact_types_get_req, artifact_post_req,
30+
artifact_types_get_req, artifact_post_req,
3131
artifact_summary_get_request, artifact_summary_post_request,
3232
artifact_patch_request, artifact_get_prep_req)
3333

@@ -234,7 +234,7 @@ def test_artifact_summary_get_request(self):
234234
with open(fp, 'w') as f:
235235
f.write('<b>HTML TEST - not important</b>\n')
236236
a = Artifact(1)
237-
a.html_summary_fp = fp
237+
a.set_html_summary(fp)
238238
self._files_to_remove.extend([fp, a.html_summary_fp[1]])
239239
exp_files.append(
240240
(a.html_summary_fp[0],
@@ -393,22 +393,6 @@ def test_artifact_patch_request_errors(self):
393393
'operations: replace'}
394394
self.assertEqual(obs, exp)
395395

396-
def test_artifact_delete_req(self):
397-
obs = artifact_delete_req(self.artifact.id, 'test@foo.bar')
398-
exp = {'status': 'success', 'message': ''}
399-
self.assertEqual(obs, exp)
400-
401-
# This is needed so the clean up works - this is a distributed system
402-
# so we need to make sure that all processes are done before we reset
403-
# the test database
404-
wait_for_prep_information_job(1)
405-
406-
def test_artifact_delete_req_no_access(self):
407-
obs = artifact_delete_req(self.artifact.id, 'demo@microbio.me')
408-
exp = {'status': 'error',
409-
'message': 'User does not have access to study'}
410-
self.assertEqual(obs, exp)
411-
412396
def test_artifact_get_prep_req(self):
413397
obs = artifact_get_prep_req('test@foo.bar', [4])
414398
exp = {'status': 'success', 'msg': '', 'data': {

qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def test_artifact_summary_get_request(self):
145145
with open(fp, 'w') as f:
146146
f.write('<b>HTML TEST - not important</b>\n')
147147
a = Artifact(1)
148-
a.html_summary_fp = fp
148+
a.set_html_summary(fp)
149149
self._files_to_remove.extend([fp, a.html_summary_fp[1]])
150150
exp_files.append(
151151
(a.html_summary_fp[0],
@@ -375,7 +375,7 @@ def test_get_artifact_summary_handler(self):
375375
with open(fp, 'w') as f:
376376
f.write('<b>HTML TEST - not important</b>\n')
377377
a = Artifact(1)
378-
a.html_summary_fp = fp
378+
a.set_html_summary(fp)
379379
self._files_to_remove.extend([fp, a.html_summary_fp[1]])
380380

381381
summary = relpath(a.html_summary_fp[1], qiita_config.base_data_dir)

0 commit comments

Comments
 (0)