Skip to content

Commit 30d7f5e

Browse files
Dev updates 2021 (#3063)
* rm key * use test_ssh_key * flake8 * add chmod * ssh_key -> ssh_key_fp * fix #3057 * adding JS for download * minor improvements * addressing @ElDeveloper comment * fix #3049 * fix #3060 * flake8 * addressing @ElDeveloper comments * Delete 81.sql * No * Yes * No * Yes * Replace qiita-spots to qiita Co-authored-by: Antonio Gonzalez <[email protected]>
1 parent 8fb9ca0 commit 30d7f5e

File tree

17 files changed

+215
-60
lines changed

17 files changed

+215
-60
lines changed

README.rst

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ typically limiting for researchers studying microbial ecology.
1919

2020
Qiita is currently in beta status. We are very open to community
2121
contributions and feedback. If you're interested in contributing to Qiita,
22-
see `CONTRIBUTING.md <https://github.com/biocore/qiita/blob/master/CONTRIBUTING.md>`__.
22+
see `CONTRIBUTING.md <https://github.com/qiita-spots/qiita/blob/master/CONTRIBUTING.md>`__.
2323
If you'd like to report bugs or request features, you can do that in the
24-
`Qiita issue tracker <https://github.com/biocore/qiita/issues>`__.
24+
`Qiita issue tracker <https://github.com/qiita-spots/qiita/issues>`__.
2525

2626
To install and configure your own Qiita server, see
27-
`INSTALL.md <https://github.com/biocore/qiita/blob/master/INSTALL.md>`__.
27+
`INSTALL.md <https://github.com/qiita-spots/qiita/blob/master/INSTALL.md>`__.
2828

2929
For more specific details about qiita visit `the Qiita main site tutorial <https://qiita.microbio.me/static/doc/html/qiita-philosophy/index.html>`__.
3030

@@ -71,9 +71,7 @@ future.
7171
existing studies by submitting a fix proposals to the authors of the study.
7272

7373

74-
.. |Build Status| image:: https://travis-ci.org/biocore/qiita.png?branch=master
75-
:target: https://travis-ci.org/biocore/qiita
76-
.. |Coverage Status| image:: https://codecov.io/gh/biocore/qiita/branch/master/graph/badge.svg
77-
:target: https://codecov.io/gh/biocore/qiita
78-
.. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg
79-
:target: https://gitter.im/biocore/qiita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
74+
.. |Build Status| image:: https://travis-ci.org/qiita-spots/qiita.png?branch=master
75+
:target: https://travis-ci.org/qiita-spots/qiita
76+
.. |Coverage Status| image:: https://codecov.io/gh/qiita-spots/qiita/branch/master/graph/badge.svg
77+
:target: https://codecov.io/gh/qiita-spots/qiita

qiita_db/metadata_template/base_metadata_template.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -558,20 +558,20 @@ def _clean_validate_template(cls, md_template, study_id,
558558
error = []
559559
if pgsql_reserved:
560560
error.append(
561-
"The following column names in the template contain PgSQL "
562-
"reserved words: %s." % ", ".join(pgsql_reserved))
561+
"These column names are PgSQL reserved words, replace them: "
562+
"~~ %s ~~." % ", ".join(pgsql_reserved))
563563
if invalid:
564564
error.append(
565-
"The following column names in the template contain invalid "
566-
"chars: %s." % ", ".join(invalid))
565+
"These column names contain invalid chars, remove or replace "
566+
"them: ~~ %s ~~." % ", ".join(invalid))
567567
if forbidden:
568568
error.append(
569-
"The following column names in the template contain invalid "
570-
"values: %s." % ", ".join(forbidden))
569+
"These column names are not valid in this information file, "
570+
"remove them: ~~ %s ~~." % ", ".join(forbidden))
571571
if qiime2_reserved:
572572
error.append(
573-
"The following column names in the template contain QIIME2 "
574-
"reserved words: %s." % ", ".join(pgsql_reserved))
573+
"These columns are QIIME2 reserved words, replace them: "
574+
" ~~ %s ~~." % ", ".join(pgsql_reserved))
575575

576576
if error:
577577
raise qdb.exceptions.QiitaDBColumnError(
@@ -1160,13 +1160,15 @@ def to_file(self, fp, samples=None):
11601160
df.to_csv(fp, index_label='sample_name', na_rep="", sep='\t',
11611161
encoding='utf-8')
11621162

1163-
def _common_to_dataframe_steps(self):
1163+
def _common_to_dataframe_steps(self, samples=None):
11641164
"""Perform the common to_dataframe steps
11651165
11661166
Returns
11671167
-------
11681168
pandas DataFrame
11691169
The metadata in the template,indexed on sample id
1170+
samples list of string, optional
1171+
A list of the sample names we actually want to retrieve
11701172
"""
11711173
with qdb.sql_connection.TRN:
11721174
# Retrieve all the information from the database
@@ -1175,7 +1177,12 @@ def _common_to_dataframe_steps(self):
11751177
FROM qiita.{0}
11761178
WHERE sample_id != '{1}'""".format(
11771179
self._table_name(self._id), QIITA_COLUMN_NAME)
1178-
qdb.sql_connection.TRN.add(sql)
1180+
if samples is None:
1181+
qdb.sql_connection.TRN.add(sql)
1182+
else:
1183+
sql += ' AND sample_id IN %s'
1184+
qdb.sql_connection.TRN.add(sql, [tuple(samples)])
1185+
11791186
# this query is going to return a tuple
11801187
# (sample_id, dict of columns/values); however it's important to
11811188
# notice that we can't assure that all column/values pairs are the

qiita_db/metadata_template/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
'EBI': Restriction(columns={'collection_timestamp': datetime,
1818
'physical_specimen_location': str,
1919
'taxon_id': int,
20+
'description': str,
2021
'scientific_name': str},
2122
error_msg="EBI submission disabled"),
2223
# The following columns are required for the official main QIITA site

qiita_db/metadata_template/sample_template.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,15 +333,17 @@ def biosample_accessions(self, value):
333333
"""
334334
self._update_accession_numbers('biosample_accession', value)
335335

336-
def to_dataframe(self, add_ebi_accessions=False):
336+
def to_dataframe(self, add_ebi_accessions=False, samples=None):
337337
"""Returns the metadata template as a dataframe
338338
339339
Parameters
340340
----------
341341
add_ebi_accessions : bool, optional
342342
If this should add the ebi accessions
343+
samples list of string, optional
344+
A list of the sample names we actually want to retrieve
343345
"""
344-
df = self._common_to_dataframe_steps()
346+
df = self._common_to_dataframe_steps(samples=samples)
345347

346348
if add_ebi_accessions:
347349
accessions = self.ebi_sample_accessions

qiita_db/metadata_template/test/test_sample_template.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,8 +1963,7 @@ def test_to_dataframe(self):
19631963
'1.SKM4.640180', '1.SKM5.640177', '1.SKM6.640187',
19641964
'1.SKM7.640188', '1.SKM8.640201', '1.SKM9.640192'}
19651965
self.assertEqual(set(obs.index), exp)
1966-
1967-
self.assertEqual(set(obs.columns), {
1966+
exp_columns = {
19681967
'physical_specimen_location', 'physical_specimen_remaining',
19691968
'dna_extracted', 'sample_type', 'collection_timestamp',
19701969
'host_subject_id', 'description', 'latitude', 'longitude',
@@ -1973,7 +1972,15 @@ def test_to_dataframe(self):
19731972
'water_content_soil', 'elevation', 'temp', 'tot_nitro',
19741973
'samp_salinity', 'altitude', 'env_biome', 'country', 'ph',
19751974
'anonymized_name', 'tot_org_carb', 'description_duplicate',
1976-
'env_feature', 'scientific_name', 'qiita_study_id'})
1975+
'env_feature', 'scientific_name', 'qiita_study_id'}
1976+
self.assertEqual(set(obs.columns), exp_columns)
1977+
1978+
# test limiting samples produced
1979+
exp_samples = set(['1.SKD4.640185', '1.SKD5.640186'])
1980+
obs = self.tester.to_dataframe(samples=exp_samples)
1981+
self.assertEqual(len(obs), 2)
1982+
self.assertEqual(set(obs.index), exp_samples)
1983+
self.assertEqual(set(obs.columns), exp_columns)
19771984

19781985
# test with add_ebi_accessions as True
19791986
obs = self.tester.to_dataframe(True)

qiita_db/processing_job.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,8 +1763,8 @@ def shape(self):
17631763
if self.command.name == 'Validate':
17641764
# Validate only has two options to calculate it's size: template (a
17651765
# job that has a preparation linked) or analysis (is from an
1766-
# analysis).
1767-
if 'template' in parameters:
1766+
# analysis). However, 'template' can be present and be None
1767+
if 'template' in parameters and parameters['template'] is not None:
17681768
try:
17691769
pt = qdb.metadata_template.prep_template.PrepTemplate(
17701770
parameters['template'])

qiita_pet/handlers/artifact_handlers/base_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def artifact_summary_get_request(user, artifact_id):
160160
buttons.append(btn_base % ('revert to sandbox', 'sandbox',
161161
'Revert to sandbox'))
162162

163-
if user.level == 'admin':
163+
if user.level == 'admin' and not study.autoloaded:
164164
if artifact.can_be_submitted_to_ebi:
165165
buttons.append(
166166
'<a class="btn btn-primary btn-sm" '

qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,22 @@ def test_artifact_summary_get_request(self):
257257
'errored_summary_jobs': []}
258258
self.assertEqual(obs, exp)
259259

260+
# the buttons shouldn't be present when the study is autoloaded
261+
study = a.study
262+
study.autoloaded = True
263+
exp['buttons'] = ('<button onclick="if (confirm(\'Are you sure you '
264+
'want to make public artifact id: 2?\')) { '
265+
'set_artifact_visibility(\'public\', 2) }" '
266+
'class="btn btn-primary btn-sm">Make public'
267+
'</button> <button onclick="if (confirm(\'Are you '
268+
'sure you want to revert to sandbox artifact id: '
269+
'2?\')) { set_artifact_visibility(\'sandbox\', 2) '
270+
'}" class="btn btn-primary btn-sm">Revert to '
271+
'sandbox</button> ' + private_download_button % 2)
272+
obs = artifact_summary_get_request(User('[email protected]'), 2)
273+
self.assertEqual(obs, exp)
274+
study.autoloaded = False
275+
260276
# analysis artifact
261277
obs = artifact_summary_get_request(user, 8)
262278
exp = {'name': 'noname',

qiita_pet/handlers/download.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ def _check_permissions(self, sid):
4646
study_info['message'], self.current_user.email, sid))
4747
return Study(sid)
4848

49-
def _generate_files(self, header_name, accessions, filename):
50-
text = "sample_name\t%s\n%s" % (header_name, '\n'.join(
51-
["%s\t%s" % (k, v) for k, v in accessions.items()]))
52-
49+
def _finish_generate_files(self, filename, text):
5350
self.set_header('Content-Description', 'text/csv')
5451
self.set_header('Expires', '0')
5552
self.set_header('Cache-Control', 'no-cache')
@@ -58,6 +55,12 @@ def _generate_files(self, header_name, accessions, filename):
5855
self.write(text)
5956
self.finish()
6057

58+
def _generate_files(self, header_name, accessions, filename):
59+
text = "sample_name\t%s\n%s" % (header_name, '\n'.join(
60+
["%s\t%s" % (k, v) for k, v in accessions.items()]))
61+
62+
self._finish_generate_files(filename, text)
63+
6164
def _list_dir_files_nginx(self, dirpath):
6265
"""Generates a nginx list of files in the given dirpath for nginx
6366
@@ -327,6 +330,25 @@ def get(self, prep_template_id):
327330
'ebi_experiment_accessions_study_%s_prep_%s.tsv' % (sid, pid))
328331

329332

333+
class DownloadSampleInfoPerPrep(BaseHandlerDownload):
334+
@authenticated
335+
@coroutine
336+
@execute_as_transaction
337+
def get(self, prep_template_id):
338+
pid = int(prep_template_id)
339+
pt = PrepTemplate(pid)
340+
sid = pt.study_id
341+
342+
self._check_permissions(sid)
343+
344+
st = SampleTemplate(sid)
345+
346+
text = st.to_dataframe(samples=list(pt)).to_csv(None, sep='\t')
347+
348+
self._finish_generate_files(
349+
'sample_information_from_prep_%s.tsv' % pid, text)
350+
351+
330352
class DownloadUpload(BaseHandlerDownload):
331353
@authenticated
332354
@coroutine

qiita_pet/handlers/upload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from tornado.web import authenticated, HTTPError
1010

1111
from os.path import join, exists
12-
from os import remove
12+
from os import remove, chmod
1313
from json import loads, dumps
1414

1515
from collections import defaultdict
@@ -142,6 +142,7 @@ def post(self, study_id):
142142

143143
with open(ssh_key_fp, 'wb') as f:
144144
f.write(ssh_key)
145+
chmod(ssh_key_fp, 0o600)
145146

146147
qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
147148
if method == 'list':

qiita_pet/templates/study_ajax/prep_summary.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ <h4>
429429
<span id="prep-name-span">{{name}}</span> - ID {{prep_id}} ({{data_type}})
430430
<a class="btn btn-default" data-toggle="modal" data-target="#update-prep-name"><span class="glyphicon glyphicon-pencil"></span> Edit name</a>
431431
<a class="btn btn-default" href="{% raw qiita_config.portal_dir %}/download/{{download_prep_id}}"><span class="glyphicon glyphicon-download-alt"></span> Prep info</a>
432+
<a class="btn btn-default" href="{% raw qiita_config.portal_dir %}/download_sample_info_per_prep/{{prep_id}}"><span class="glyphicon glyphicon-download-alt"></span> Sample info (only this prep)</a>
432433
{% if is_submitted_to_ebi %}
433434
<a class="btn btn-default" href="{% raw qiita_config.portal_dir %}/download_ebi_accessions/experiments/{{prep_id}}"><span class="glyphicon glyphicon-download-alt"></span> EBI experiment accessions</a>
434435
{% end %}

qiita_pet/templates/study_ajax/sample_prep_summary.html

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,44 @@
5252
sampleTemplatePage.$refs.stElem.deleteSamples(to_delete);
5353
}
5454
}
55+
56+
/**
57+
*
58+
* Function to download the data displayed in the page
59+
*
60+
*/
61+
function download_summary(){
62+
var information = [];
63+
var prep_names = {% raw columns %};
64+
65+
// adding header
66+
var header = ['sample_id']
67+
$.each(prep_colums, function(i, prep){
68+
header.push(prep_names[prep]);
69+
});
70+
information.push(header.join('\t'))
71+
72+
// adding data
73+
$.each(rows, function (i, row){
74+
var line = [row['sample']]
75+
$.each(prep_colums, function(i, prep){
76+
line.push(row[prep]);
77+
});
78+
information.push(line.join('\t'));
79+
});
80+
81+
information = information.join('\n');
82+
83+
// downloading file
84+
var element = document.createElement('a');
85+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(information));
86+
element.setAttribute('download', 'study_{{study_id}}_sample_preparations_summary.tsv');
87+
element.style.display = 'none';
88+
document.body.appendChild(element);
89+
element.click();
90+
document.body.removeChild(element);
91+
}
92+
5593
var columns = [
5694
{ 'name': '<input type="checkbox" onchange="toggleCheckboxes(this)">',
5795
'field': 'sample-delete', 'id': 'sample-delete', width: 69, sortable: false, formatter: linkFormatter },
@@ -271,6 +309,9 @@
271309
<tr>
272310
<td>
273311
<h3>Sample Summary</h3><br/>
312+
<button class="btn btn-default st-interactive" onclick="download_summary();">
313+
<span class="glyphicon glyphicon-download-alt"></span> Summary
314+
</button>
274315
<button class="btn btn-danger st-interactive" onclick="deleteIndividualSamples()">
275316
<span class="glyphicon glyphicon-trash"></span> Delete Selected
276317
</button>
@@ -280,6 +321,7 @@ <h3>Sample Summary</h3><br/>
280321
</td>
281322
<td style="text-align: right">
282323
Add sample column information to table
324+
<br/>
283325
<select id="metadata_category" name="metadata_category">
284326
<option value=""></option>
285327
{% for col in categories %}

qiita_pet/test/test_download.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
# The full license is in the file LICENSE, distributed with this software.
77
# -----------------------------------------------------------------------------
88

9+
import pandas as pd
910
from unittest import main
1011
from mock import Mock
1112
from os.path import exists, isdir, join, basename
1213
from os import remove, makedirs, close
1314
from shutil import rmtree
1415
from tempfile import mkdtemp, mkstemp
16+
from io import StringIO
1517

1618
from biom.util import biom_open
1719
from biom import example_table as et
@@ -340,6 +342,25 @@ def test_download(self):
340342
self.assertEqual(response.code, 405)
341343

342344

345+
class TestDownloadSampleInfoPerPrep(TestHandlerBase):
346+
347+
def test_download(self):
348+
# check success
349+
response = self.get('/download_sample_info_per_prep/1')
350+
self.assertEqual(response.code, 200)
351+
352+
df = pd.read_csv(StringIO(response.body.decode('ascii')), sep='\t')
353+
# just testing shape as the actual content is tested in the dataframe
354+
# generation
355+
self.assertEqual(df.shape, (27, 33))
356+
357+
# changing user so we can test the failures
358+
BaseHandler.get_current_user = Mock(
359+
return_value=User("[email protected]"))
360+
response = self.get('/download_sample_info_per_prep/1')
361+
self.assertEqual(response.code, 405)
362+
363+
343364
class TestDownloadUpload(TestHandlerBase):
344365

345366
def test_download(self):

qiita_pet/webserver.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
DownloadHandler, DownloadStudyBIOMSHandler, DownloadRelease,
5252
DownloadRawData, DownloadEBISampleAccessions, DownloadEBIPrepAccessions,
5353
DownloadUpload, DownloadPublicHandler, DownloadPublicArtifactHandler,
54-
DownloadPrivateArtifactHandler)
54+
DownloadSampleInfoPerPrep, DownloadPrivateArtifactHandler)
5555
from qiita_pet.handlers.prep_template import (
5656
PrepTemplateHandler, PrepTemplateGraphHandler, PrepTemplateJobHandler)
5757
from qiita_pet.handlers.ontology import OntologyHandler
@@ -183,6 +183,8 @@ def __init__(self):
183183
(r"/download_raw_data/(.*)", DownloadRawData),
184184
(r"/download_ebi_accessions/samples/(.*)",
185185
DownloadEBISampleAccessions),
186+
(r"/download_sample_info_per_prep/(.*)",
187+
DownloadSampleInfoPerPrep),
186188
(r"/download_ebi_accessions/experiments/(.*)",
187189
DownloadEBIPrepAccessions),
188190
(r"/download_upload/(.*)", DownloadUpload),

0 commit comments

Comments
 (0)