diff --git a/knimin/handlers/ag_pulldown.py b/knimin/handlers/ag_pulldown.py
index b6190c8..1d66b04 100644
--- a/knimin/handlers/ag_pulldown.py
+++ b/knimin/handlers/ag_pulldown.py
@@ -1,5 +1,7 @@
from tornado.web import authenticated
from future.utils import viewitems
+from StringIO import StringIO
+import pandas as pd
from knimin.handlers.base import BaseHandler
from knimin import db
@@ -13,17 +15,20 @@ class AGPulldownHandler(BaseHandler):
def get(self):
surveys = db.list_external_surveys()
self.render("ag_pulldown.html", currentuser=self.current_user,
- barcodes=[], surveys=surveys, errors='')
+ barcodes=[], surveys=surveys, errors='',
+ agsurveys=db.list_ag_surveys(), merged='False')
@authenticated
def post(self):
# Do nothing if no file given
if 'barcodes' not in self.request.files:
surveys = db.list_external_surveys()
+ ags = db.list_ag_surveys(map(int, self.get_arguments('agsurveys')))
self.render("ag_pulldown.html", currentuser=self.current_user,
barcodes='', blanks='', external='', surveys=surveys,
errors="No barcode file given, thus nothing could "
- "be pulled down.")
+ "be pulled down.", agsurveys=ags,
+ merged=self.get_argument('merged', default='False'))
return
# Get file information, ignoring commented out lines
fileinfo = self.request.files['barcodes'][0]['body']
@@ -41,24 +46,27 @@ def post(self):
else:
external = ''
surveys = db.list_external_surveys()
+ ags = db.list_ag_surveys(map(int, self.get_arguments('agsurveys')))
self.render("ag_pulldown.html", currentuser=self.current_user,
barcodes=",".join(barcodes), blanks=",".join(blanks),
- surveys=surveys, external=external, errors='')
+ surveys=surveys, external=external, errors='',
+ agsurveys=ags,
+ merged=self.get_argument('merged', default='False'))
@set_access(['Metadata Pulldown'])
class AGPulldownDLHandler(BaseHandler):
@authenticated
def post(self):
- barcodes = self.get_argument('barcodes').split(',')
- if self.get_argument('blanks'):
- blanks = self.get_argument('blanks').split(',')
- else:
- blanks = []
- if self.get_argument('external'):
- external = self.get_argument('external').split(',')
- else:
- external = []
+ barcodes = listify(self.get_arguments('barcodes'))
+ blanks = listify(self.get_arguments('blanks'))
+ # query which surveys have been selected by the user
+ selected_ag_surveys = listify(
+ self.get_arguments('selected_ag_surveys'))
+ external = listify(self.get_arguments('external'))
+
+ selected_ag_surveys = list(map(int, selected_ag_surveys))
+
# Get metadata and create zip file
metadata, failures = db.pulldown(barcodes, blanks, external)
@@ -67,8 +75,43 @@ def post(self):
failtext = ("The following barcodes were not retrieved "
"for any survey:\n%s" % failed)
meta_zip.append("failures.txt", failtext)
+
+ # check database about what surveys are available
+ available_agsurveys = {}
+ for (_id, name, _) in db.list_ag_surveys():
+ available_agsurveys[_id] = name.replace(' ', '_')
+
+ results_as_pd = []
for survey, meta in viewitems(metadata):
- meta_zip.append('survey_%s_md.txt' % survey, meta)
+ # only create files for those surveys that have been selected by
+ # the user. Note that ids from the DB are negative, in metadata
+ # they are positive!
+ # Currently, I (Stefan Janssen) don't have test data for external
+ # surveys, thus I don't know their 'survey' value. I expect it to
+ # be the name of the external survey. In order to not block their
+ # pulldown I check that a skipped survey ID must be in the set of
+ # all available surveys.
+ survey = -1 * survey
+ if (survey in selected_ag_surveys) or \
+ (survey not in available_agsurveys):
+ meta_zip.append('survey_%s_md.txt' %
+ available_agsurveys[survey], meta)
+ # transform each survey into a pandas dataframe for later merge
+ # read all columns as string to avoid unintened conversions,
+ # like cutting leading zeros of barcodes
+ pd_meta = pd.read_csv(StringIO(meta), sep="\t", dtype=str)
+ # reset the index to barcodes = here sample_name
+ pd_meta.set_index('sample_name', inplace=True)
+ results_as_pd.append(pd_meta)
+
+ # add the merged table of all selected surveys to the zip archive
+ if self.get_argument('merged', default='False') == 'True':
+ pd_all = pd.DataFrame()
+ if len(results_as_pd) > 0:
+ pd_all = pd.concat(results_as_pd, join='outer', axis=1)
+ meta_zip.append('surveys_merged_md.txt',
+ pd_all.to_csv(sep='\t',
+ index_label='sample_name'))
# write out zip file
self.add_header('Content-type', 'application/octet-stream')
@@ -92,3 +135,22 @@ def get(self):
except Exception as e:
msg = 'ERROR: %s' % str(e)
self.write(msg)
+
+
+def listify(_list):
+ """ Returns a flat list of str for either list of str (unchanged) or a one-
+ element list of str - delimited by ',' - into a list of str.
+
+ Parameters
+ ----------
+ _list : [str]
+ Input list of str
+
+ Returns
+ -------
+ A list of str. If single element was a comma delimited str with x parts,
+ the list will contain those x elements."""
+ if len(_list) == 1:
+ if ',' in _list[0]:
+ _list = _list[0].split(',')
+ return _list
diff --git a/knimin/lib/data_access.py b/knimin/lib/data_access.py
index 55f6f48..34a1bdc 100644
--- a/knimin/lib/data_access.py
+++ b/knimin/lib/data_access.py
@@ -1685,6 +1685,30 @@ def add_external_survey(self, survey, description, url):
RETURNING external_survey_id"""
return self._con.execute_fetchone(sql, [survey, description, url])[0]
+ def list_ag_surveys(self, selected=None):
+ """Returns the list of american gut survey names.
+
+ Parameters
+ ----------
+ selected : list of int
+ The returned list's third element indicates if a survey has been
+ "chosen". If selected is None, all surveys will be "chosen",
+ otherwise only surveys whose ID is in selected are "chosen".
+
+ Returns
+ -------
+ list of (int, str, bool)
+ first element is the group_order number
+ second element is the group name
+ third element is the information if user selected this survey for
+ pulldown. All surveys are selected if selected is None.
+ """
+ sql = """SELECT group_order, american
+ FROM ag.survey_group
+ WHERE group_order < 0"""
+ return [(id_, name, (selected is None) or (id_ in selected))
+ for [id_, name] in self._con.execute_fetchall(sql)]
+
def list_external_surveys(self):
"""Returns list of external survey names
diff --git a/knimin/lib/mem_zip.py b/knimin/lib/mem_zip.py
index 4c4b8a2..66a7fe1 100644
--- a/knimin/lib/mem_zip.py
+++ b/knimin/lib/mem_zip.py
@@ -61,6 +61,45 @@ def write_to_buffer(self):
return self.in_memory_data.getvalue()
+def extract_zip(input_zip):
+ """ Reads all files of a zip file from disk.
+
+ A helper function to read in all files of a zip archive as strings and
+ return a dict of those strings where the keys are the filenames.
+
+ Parameters
+ ----------
+ input_zip : str
+ The filename of the archive.
+
+ Returns
+ -------
+ A dict of str: keys = filenames in archive, values = content of files
+ """
+
+ input_zip = zipfile.ZipFile(input_zip)
+ return {name: input_zip.read(name) for name in input_zip.namelist()}
+
+
+def sneak_files(archive, len=1000):
+ """ Returns the first characters of each file in an zip archive.
+
+ Parameters
+ ----------
+ archive : dict{str : filename, str : filecontents}
+ The already extracted zip archive in form of a dict, where keys are
+ filenames and values are the content of the file.
+ len : int
+ Number of characters returned from each file.
+ Default: 1000.
+
+ Returns
+ -------
+ dict{str, str} where the first component is the filename and the second
+ the first characters of the file."""
+ return map(lambda (k, v): {k: v[:len]}, archive.items())
+
+
if __name__ == "__main__":
# Run a test
imz = InMemoryZip()
diff --git a/knimin/lib/tests/test_data_access.py b/knimin/lib/tests/test_data_access.py
index 5f4a73e..a776937 100644
--- a/knimin/lib/tests/test_data_access.py
+++ b/knimin/lib/tests/test_data_access.py
@@ -272,55 +272,54 @@ def test_get_ag_barcode_details(self):
obs = db.get_ag_barcode_details(['000018046'])
ag_login_id = '0060a301-e5bf-6a4e-e050-8a800c5d49b7'
exp = {'000018046': {
- 'ag_kit_barcode_id': '0060a301-e5c1-6a4e-e050-8a800c5d49b7',
- 'verification_email_sent': 'n',
- 'pass_reset_code': None,
- 'vioscreen_status': 3,
- 'sample_barcode_file': '000018046.jpg',
- 'environment_sampled': None,
- 'supplied_kit_id': db.ut_get_supplied_kit_id(ag_login_id),
- 'withdrawn': None,
- 'kit_verified': 'y',
- # 'city': 'REMOVED',
- 'ag_kit_id': '0060a301-e5c0-6a4e-e050-8a800c5d49b7',
- # 'zip': 'REMOVED',
- 'ag_login_id': ag_login_id,
- # 'state': 'REMOVED',
- 'results_ready': 'Y',
- 'moldy': 'N',
- # The key 'registered_on' is a time stamp when the database is
- # created. It is unique per deployment.
- # 'registered_on': datetime.datetime(2016, 8, 17, 10, 47, 2,
- # 713292),
- # 'kit_password': ('$2a$10$2.6Y9HmBqUFmSvKCjWmBte70WF.zd3h4Vqb'
- # 'hLMQK1xP67Aj3rei86'),
- # 'deposited': False,
- 'sample_date': datetime.date(2014, 8, 13),
- # 'email': 'REMOVED',
- 'print_results': False,
- 'open_humans_token': None,
- # 'elevation': 0.0,
- 'refunded': None,
- # 'other_text': 'REMOVED',
- 'barcode': '000018046',
- 'swabs_per_kit': 1L,
- # 'kit_verification_code': '60260',
- # 'latitude': 0.0,
- 'cannot_geocode': None,
- # 'address': 'REMOVED',
- 'date_of_last_email': datetime.date(2014, 8, 15),
- 'site_sampled': 'Stool',
- # 'name': 'REMOVED',
- 'sample_time': datetime.time(11, 15),
- # 'notes': 'REMOVED',
- 'overloaded': 'N',
- # 'longitude': 0.0,
- 'pass_reset_time': None,
- # 'country': 'REMOVED',
- 'survey_id': '084532330aca5885',
- 'other': 'N',
- 'sample_barcode_file_md5': None
- }}
+ 'ag_kit_barcode_id': '0060a301-e5c1-6a4e-e050-8a800c5d49b7',
+ 'verification_email_sent': 'n',
+ 'pass_reset_code': None,
+ 'vioscreen_status': 3,
+ 'sample_barcode_file': '000018046.jpg',
+ 'environment_sampled': None,
+ 'supplied_kit_id': db.ut_get_supplied_kit_id(ag_login_id),
+ 'withdrawn': None,
+ 'kit_verified': 'y',
+ # 'city': 'REMOVED',
+ 'ag_kit_id': '0060a301-e5c0-6a4e-e050-8a800c5d49b7',
+ # 'zip': 'REMOVED',
+ 'ag_login_id': ag_login_id,
+ # 'state': 'REMOVED',
+ 'results_ready': 'Y',
+ 'moldy': 'N',
+ # The key 'registered_on' is a time stamp when the database is
+ # created. It is unique per deployment.
+ # 'registered_on': datetime.datetime(2016, 8, 17, 10, 47, 2,
+ # 713292),
+ # 'kit_password': ('$2a$10$2.6Y9HmBqUFmSvKCjWmBte70WF.zd3h4Vqb'
+ # 'hLMQK1xP67Aj3rei86'),
+ # 'deposited': False,
+ 'sample_date': datetime.date(2014, 8, 13),
+ # 'email': 'REMOVED',
+ 'print_results': False,
+ 'open_humans_token': None,
+ # 'elevation': 0.0,
+ 'refunded': None,
+ # 'other_text': 'REMOVED',
+ 'barcode': '000018046',
+ 'swabs_per_kit': 1L,
+ # 'kit_verification_code': '60260',
+ # 'latitude': 0.0,
+ 'cannot_geocode': None,
+ # 'address': 'REMOVED',
+ 'date_of_last_email': datetime.date(2014, 8, 15),
+ 'site_sampled': 'Stool',
+ # 'name': 'REMOVED',
+ 'sample_time': datetime.time(11, 15),
+ # 'notes': 'REMOVED',
+ 'overloaded': 'N',
+ # 'longitude': 0.0,
+ 'pass_reset_time': None,
+ # 'country': 'REMOVED',
+ 'survey_id': '084532330aca5885',
+ 'other': 'N',
+ 'sample_barcode_file_md5': None}}
participant_names = db.ut_get_participant_names_from_ag_login_id(
ag_login_id)
for key in obs:
@@ -329,6 +328,21 @@ def test_get_ag_barcode_details(self):
self.assertEqual({k: obs[key][k] for k in exp[key]}, exp[key])
self.assertIn(obs[key]['participant_name'], participant_names)
+ def test_list_ag_surveys(self):
+ truth = [(-1, 'Personal Information', True),
+ (-2, 'Pet Information', True),
+ (-3, 'Fermented Foods', True),
+ (-4, 'Surfers', True),
+ (-5, 'Personal_Microbiome', True)]
+ self.assertItemsEqual(db.list_ag_surveys(), truth)
+
+ truth = [(-1, 'Personal Information', False),
+ (-2, 'Pet Information', True),
+ (-3, 'Fermented Foods', False),
+ (-4, 'Surfers', True),
+ (-5, 'Personal_Microbiome', False)]
+ self.assertItemsEqual(db.list_ag_surveys([-2, -4]), truth)
+
if __name__ == "__main__":
main()
diff --git a/knimin/lib/tests/test_mem_zip.py b/knimin/lib/tests/test_mem_zip.py
index 5f05978..eb19f6e 100644
--- a/knimin/lib/tests/test_mem_zip.py
+++ b/knimin/lib/tests/test_mem_zip.py
@@ -1,8 +1,9 @@
import unittest
-from knimin.lib.mem_zip import InMemoryZip
+from knimin.lib.mem_zip import InMemoryZip, extract_zip, sneak_files
import zipfile
import os
import io
+from os.path import join, dirname, realpath
class TestInMemoryZip(unittest.TestCase):
@@ -50,6 +51,33 @@ def test_write_to_buffer(self):
res_contents = zhandle.read(self.test_fname)
self.assertEqual(res_contents, exp_contents)
+ def test_extract_zip(self):
+ fp_zip = join(dirname(realpath(__file__)), '..', '..', 'tests', 'data',
+ 'results_multiplesurvey_barcodes.zip')
+ obs = extract_zip(fp_zip)
+ exp_filenames = ['failures.txt', 'survey_Fermented_Foods_md.txt',
+ 'survey_Personal_Information_md.txt',
+ 'survey_Personal_Microbiome_md.txt',
+ 'survey_Pet_Information_md.txt',
+ 'surveys_merged_md.txt', 'survey_Surfers_md.txt']
+ # check filenames
+ self.assertEqual(sorted(obs.keys()), sorted(exp_filenames))
+ # check file contents very briefly
+ self.assertIn('SURF_BOARD_TYPE', obs['survey_Surfers_md.txt'])
+
+ def test_sneak_files(self):
+ fp_zip = join(dirname(realpath(__file__)), '..', '..', 'tests', 'data',
+ 'results_multiplesurvey_barcodes.zip')
+ exp = [{'survey_Personal_Microbiome_md.txt': 'sample_name\tPM_AGE\tP'},
+ {'survey_Pet_Information_md.txt': 'sample_name\tALTITUDE'},
+ {'failures.txt': 'The following barcod'},
+ {'survey_Fermented_Foods_md.txt': 'sample_name\tFERMENTE'},
+ {'survey_Surfers_md.txt': 'sample_name\tSURF_BOA'},
+ {'survey_Personal_Information_md.txt': 'sample_name\tACNE_MED'},
+ {'surveys_merged_md.txt': 'sample_name\tACNE_MED'}]
+ obs = sneak_files(extract_zip(fp_zip), 20)
+ self.assertEqual(exp, obs)
+
if __name__ == '__main__':
unittest.main()
diff --git a/knimin/templates/ag_pulldown.html b/knimin/templates/ag_pulldown.html
index 0f10223..80dd64d 100644
--- a/knimin/templates/ag_pulldown.html
+++ b/knimin/templates/ag_pulldown.html
@@ -52,6 +52,15 @@
dummy.addParameter('barcodes', '{{barcodes}}');
dummy.addParameter('blanks', '{{blanks}}');
dummy.addParameter('external', '{{external}}');
+ slist = [
+ {% for s in agsurveys %}
+ {% if s[2] == True %}
+ {{s[0]}},
+ {% end %}
+ {% end %}
+ ];
+ dummy.addParameter('selected_ag_surveys', slist);
+ dummy.addParameter('merged', '{{merged}}');
dummy.send();
{% end %}
});
@@ -71,14 +80,34 @@
Metadata Pulldown
+
+
External Survey
+
Select which external surveys should be included in the pulldown archive.
{% for s in surveys %}
{% end %}
+{% if merged == 'True' %}
+Add file containing columns of all selected surveys
+{% else %}
+Add a file "surveys_merged_md.txt" that will contain columns of all selected surveys.
+{% end %}
{% raw errors %}
-{% end %}
\ No newline at end of file
+{% end %}
diff --git a/knimin/tests/data/barcodes.txt b/knimin/tests/data/barcodes.txt
index 373babe..87f9b65 100644
--- a/knimin/tests/data/barcodes.txt
+++ b/knimin/tests/data/barcodes.txt
@@ -14,9 +14,7 @@ BLANK100001453 notInDB
000015297
000015298
000015299
-000015300
000016280
000016281
-000016282
000016283
000016284
diff --git a/knimin/tests/data/multiplesurvey_barcodes.txt b/knimin/tests/data/multiplesurvey_barcodes.txt
new file mode 100644
index 0000000..1c0c032
--- /dev/null
+++ b/knimin/tests/data/multiplesurvey_barcodes.txt
@@ -0,0 +1,20 @@
+000001000 infos about barcode survey_group: -1 survey_id: 48c83b76031b7580
+000001001 infos about barcode survey_group: -1 survey_id: 0b0832aafb76068d
+000001002 infos about barcode survey_group: -1 survey_id: 2d19912f1784a4bf
+000037583 infos about barcode survey_group: -2 survey_id: 0696e13141fb4d13
+000066526 infos about barcode survey_group: -2 survey_id: 0c42c7b89d21d814
+000031568 infos about barcode survey_group: -2 survey_id: 0d4d925e045f9353
+000037555 infos about barcode survey_group: -3 survey_id: 05109e6adfa45c70
+000065893 infos about barcode survey_group: -3 survey_id: 051117c37ffd75d7
+000067690 infos about barcode survey_group: -3 survey_id: 061b62bb33a480d6
+000049932 infos about barcode survey_group: -4 survey_id: 005be6bd1a714085
+000063380 infos about barcode survey_group: -4 survey_id: 0d57b2d00370a907
+000063381 infos about barcode survey_group: -4 survey_id: 0d57b2d00370a907
+000006616 infos about barcode survey_group: -5 survey_id: 864923798da97c70
+000030821 infos about barcode survey_group: -1 survey_id: 37af4d8102234cfc
+000030822 infos about barcode survey_group: -1 survey_id: 37af4d8102234cfc
+000030823 infos about barcode survey_group: -1 survey_id: 37af4d8102234cfc
+000069020 infos about barcode survey_group: -4 survey_id: e60a2eb5001e48c6
+000069021 infos about barcode survey_group: -4 survey_id: e60a2eb5001e48c6
+000069022 infos about barcode survey_group: -4 survey_id: e60a2eb5001e48c6
+
diff --git a/knimin/tests/data/results_barcodes.zip b/knimin/tests/data/results_barcodes.zip
new file mode 100644
index 0000000..fed5b25
Binary files /dev/null and b/knimin/tests/data/results_barcodes.zip differ
diff --git a/knimin/tests/data/results_multiplesurvey_barcodes.zip b/knimin/tests/data/results_multiplesurvey_barcodes.zip
new file mode 100644
index 0000000..fa4bde5
Binary files /dev/null and b/knimin/tests/data/results_multiplesurvey_barcodes.zip differ
diff --git a/knimin/tests/test_ag_pulldown.py b/knimin/tests/test_ag_pulldown.py
index a168648..99f95b9 100644
--- a/knimin/tests/test_ag_pulldown.py
+++ b/knimin/tests/test_ag_pulldown.py
@@ -1,11 +1,14 @@
from unittest import main
import os
from os.path import dirname, realpath, join
+from tempfile import NamedTemporaryFile
from tornado.escape import url_escape
from knimin.tests.tornado_test_base import TestHandlerBase
from knimin import db
+from knimin.lib.mem_zip import extract_zip, sneak_files
+from knimin.handlers.ag_pulldown import listify
class testUpdateEBIStatusHandler(TestHandlerBase):
@@ -53,6 +56,13 @@ def test_get(self):
self.assertIn("" % (survey, survey),
response.body)
self.assertNotIn('', response.body)
+ for (_id, name, selected) in db.list_ag_surveys():
+ if selected:
+ self.assertIn("" %
+ (_id, name), response.body)
+ else:
+ self.assertIn("" %
+ (_id, name), response.body)
def test_post(self):
self.mock_login_admin()
@@ -89,50 +99,110 @@ def test_get_not_authed(self):
def test_post(self):
self.mock_login_admin()
response = self.post('/ag_pulldown/download/',
- {'barcodes': ['000001445',
- '000001446',
- '000001447',
- '000001448',
- '100001449',
- '000016180',
- '000015296',
- '000015297',
- '000015298',
- '000015299',
- '000015300',
- '000016280',
- '000016281',
- '000016282',
- '000016283',
+ {'barcodes': ['000001448', '000001447',
+ '100001449', '000001445',
+ '000015296', '000015297',
+ '000015298', '000015299',
+ '000016180', '000016280',
+ '000016281', '000016283',
'000016284'],
- 'blanks': ['BLANK000001449',
- 'BLANK000001453',
+ 'blanks': ['BLANK000001449', 'BLANK000001453',
'BLANK100001453'],
- 'external': db.list_external_surveys()[:1]})
+ 'external': db.list_external_surveys()[:1],
+ 'selected_ag_surveys': [-1, -2, -3, -4, -5],
+ 'merged': 'True'})
self.assertEqual(response.headers['Content-Disposition'],
'attachment; filename=metadata.zip')
self.assertIn('failures.txt', response.body)
- self.assertIn('survey_1_md.txt', response.body)
+ self.assertIn('survey_Personal_Information_md.txt', response.body)
+
+ # store the resulting zip archive to disc ...
+ tmpfile = NamedTemporaryFile(mode='w', delete=False,
+ prefix='metadata_pulldown_single_',
+ suffix='.zip')
+ tmpfile.write(response.body)
+ tmpfile.close()
+ # ... and read the content as dict of strings
+ result = extract_zip(tmpfile.name)
+ os.remove(tmpfile.name)
+
+ # read in the true content from data dir for comparison
+ truth = extract_zip(join(dirname(realpath(__file__)), 'data',
+ 'results_barcodes.zip'))
+ self.maxDiff = None
+ self.assertEqual(sneak_files(result), sneak_files(truth))
+
+ def test_post_multiple_surverys(self):
+ self.mock_login_admin()
+ response = self.post('/ag_pulldown/download/',
+ {'barcodes': ['000001000', '000001001',
+ '000001002', '000037583',
+ '000066526', '000031568',
+ '000037555', '000065893',
+ '000067690', '000049932',
+ '000063380', '000063381',
+ '000006616', '000030821',
+ '000030822', '000030823',
+ '000069020', '000069021'
+ '000069022'],
+ 'blanks': [],
+ 'external': [],
+ 'selected_ag_surveys': [-1, -2, -3, -4, -5],
+ 'merged': 'True'})
+ self.assertEqual(response.headers['Content-Disposition'],
+ 'attachment; filename=metadata.zip')
+
+ # store the resulting zip archive to disc ...
+ tmpfile = NamedTemporaryFile(mode='w', delete=False,
+ prefix='metadata_pulldown_multiple_',
+ suffix='.zip')
+ tmpfile.write(response.body)
+ tmpfile.close()
+ # ... and read the content as dict of strings
+ result = extract_zip(tmpfile.name)
+ os.remove(tmpfile.name)
+
+ # read in the true content from data dir for comparison
+ truth = extract_zip(join(dirname(realpath(__file__)), 'data',
+ 'results_multiplesurvey_barcodes.zip'))
+
+ self.assertEqual(sneak_files(result), sneak_files(truth))
+
+ def test_post_select_surveys(self):
+ self.mock_login_admin()
+ response = self.post('/ag_pulldown/download/',
+ {'barcodes': ['000037555', '000065893',
+ '000067690', '000037583',
+ '000066526', '000031568'],
+ 'blanks': [],
+ 'external': [],
+ 'selected_ag_surveys': [-2, -3, -8],
+ 'merged': 'False'})
+ # store the resulting zip archive to disc ...
+ tmpfile = NamedTemporaryFile(mode='w', delete=False,
+ prefix='metadata_pulldown_multiple_sel_',
+ suffix='.zip')
+ tmpfile.write(response.body)
+ tmpfile.close()
+ # ... and read the content as dict of strings
+ result = extract_zip(tmpfile.name)
+ self.assertItemsEqual(result.keys(),
+ ['failures.txt',
+ 'survey_Fermented_Foods_md.txt',
+ 'survey_Pet_Information_md.txt'])
+ os.remove(tmpfile.name)
# no blanks
response = self.post('/ag_pulldown/download/',
- {'barcodes': ['000001445',
- '000001446',
- '000001447',
- '000001448',
- '100001449',
- '000016180',
- '000015296',
- '000015297',
- '000015298',
- '000015299',
- '000015300',
- '000016280',
- '000016281',
- '000016282',
- '000016283',
- '000016284'],
- 'blanks': '',
+ {'barcodes': ('000001445', '000001446',
+ '000001447', '000001448',
+ '100001449', '000016180',
+ '000015296', '000015297',
+ '000015298', '000015299',
+ '000015300', '000016280',
+ '000016281', '000016282',
+ '000016283', '000016284'),
+ 'blanks': [],
'external': db.list_external_surveys()[:1]})
self.assertEqual(response.code, 200)
self.assertEqual(response.headers['Content-Disposition'],
@@ -159,11 +229,66 @@ def test_post(self):
'blanks': ['BLANK000001449',
'BLANK000001453',
'BLANK100001453'],
- 'external': ''})
+ 'external': []})
self.assertEqual(response.code, 200)
self.assertEqual(response.headers['Content-Disposition'],
'attachment; filename=metadata.zip')
+ def test_post_select_surveys_htmlencoding(self):
+ # the interface html page provides arguments as one concatenated string
+ # which is not a list of strings. Here, I test if this other behaviour
+ # also works.
+ self.mock_login_admin()
+
+ response = self.post('/ag_pulldown/download/',
+ {'barcodes': ('000037555,000065893,000067690,'
+ '000037583,000066526,000031568'),
+ 'blanks': '',
+ 'external': '',
+ 'selected_ag_surveys': '-2,-3,-8',
+ 'merged': 'False'})
+ # store the resulting zip archive to disc ...
+ tmpfile = NamedTemporaryFile(mode='w', delete=False,
+ prefix='metadata_pulldown_multiple_sel_',
+ suffix='.zip')
+ tmpfile.write(response.body)
+ tmpfile.close()
+ # ... and read the content as dict of strings
+ result = extract_zip(tmpfile.name)
+ self.assertItemsEqual(result.keys(),
+ ['failures.txt',
+ 'survey_Fermented_Foods_md.txt',
+ 'survey_Pet_Information_md.txt'])
+ os.remove(tmpfile.name)
+
+ response = self.post('/ag_pulldown/download/',
+ {'barcodes': ('000037555,000065893,000067690,'
+ '000037583,000066526,000031568'),
+ 'blanks': '',
+ 'external': '',
+ 'selected_ag_surveys': '-3',
+ 'merged': 'False'})
+ # store the resulting zip archive to disc ...
+ tmpfile = NamedTemporaryFile(mode='w', delete=False,
+ prefix='metadata_pulldown_multiple_sel_',
+ suffix='.zip')
+ tmpfile.write(response.body)
+ tmpfile.close()
+ # ... and read the content as dict of strings
+ result = extract_zip(tmpfile.name)
+ self.assertItemsEqual(result.keys(),
+ ['failures.txt',
+ 'survey_Fermented_Foods_md.txt'])
+ os.remove(tmpfile.name)
+
+ def test_listify(self):
+ obs = listify(['a', 'b', 'c'])
+ exp = ['a', 'b', 'c']
+ self.assertItemsEqual(obs, exp)
+
+ obs = listify(['a,b,c'])
+ self.assertItemsEqual(obs, exp)
+
if __name__ == "__main__":
main()