From 6e63787d06317984ee4e075924e27a3ca2ab6403 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Fri, 13 Apr 2012 16:58:16 -0400 Subject: [PATCH 01/20] added error to the google doc test --- main/tests/test_base.py | 10 ++++++++++ main/tests/test_google_docs_export.py | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/main/tests/test_base.py b/main/tests/test_base.py index fb54a92ed..1512e25e3 100644 --- a/main/tests/test_base.py +++ b/main/tests/test_base.py @@ -23,6 +23,11 @@ def _login(self, username, password): assert client.login(username=username, password=password) return client + def _logout(self, client=None): + if not client: + client = self.client + client.logout() + def _create_user_and_login(self, username="bob", password="bob"): self.user = self._create_user(username, password) self.client = self._login(username, password) @@ -37,6 +42,11 @@ def _publish_xls_file(self, path): post_data = {'xls_file': xls_file} return self.client.post('/%s/' % self.user.username, post_data) + def _share_form_data(self, id_string='transportation_2011_07_25'): + xform = XForm.objects.get(id_string=id_string) + xform.shared_data = True + xform.save() + def _publish_transportation_form(self): xls_path = os.path.join(self.this_directory, "fixtures", "transportation", "transportation.xls") diff --git a/main/tests/test_google_docs_export.py b/main/tests/test_google_docs_export.py index 3b2ac5bd4..2ca64f7af 100644 --- a/main/tests/test_google_docs_export.py +++ b/main/tests/test_google_docs_export.py @@ -25,6 +25,15 @@ def test_google_docs_export(self): })) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], 'https://docs.google.com') + # share the data, log out, and check the export + self._share_form_data() + self._logout() + response = self.client.get(reverse(google_xls_export, kwargs={ + 'username': self.user.username, + 'id_string': self.xform.id_string + })) + self.assertEqual(response.status_code, 302) + self.assertEqual(response['Location'], 'https://docs.google.com') def _refresh_token(self): self.assertEqual(TokenStorageModel.objects.all().count(), 0) From a25267b3c2cec49ae69a98aac05d07524536ad51 Mon Sep 17 00:00:00 2001 From: Ukang'a Dickson Date: Tue, 17 Apr 2012 12:00:05 +0300 Subject: [PATCH 02/20] redirects to login page --- main/tests/test_google_docs_export.py | 1 - 1 file changed, 1 deletion(-) diff --git a/main/tests/test_google_docs_export.py b/main/tests/test_google_docs_export.py index 2ca64f7af..e50e9fc1e 100644 --- a/main/tests/test_google_docs_export.py +++ b/main/tests/test_google_docs_export.py @@ -33,7 +33,6 @@ def test_google_docs_export(self): 'id_string': self.xform.id_string })) self.assertEqual(response.status_code, 302) - self.assertEqual(response['Location'], 'https://docs.google.com') def _refresh_token(self): self.assertEqual(TokenStorageModel.objects.all().count(), 0) From 972f14b00493dd45c13106e3564b948cdc798cd3 Mon Sep 17 00:00:00 2001 From: Ukang'a Dickson Date: Tue, 17 Apr 2012 12:00:48 +0300 Subject: [PATCH 03/20] user has to be logged in on formhub to export to google docs --- odk_viewer/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/odk_viewer/views.py b/odk_viewer/views.py index ec71a6410..dc389b76a 100644 --- a/odk_viewer/views.py +++ b/odk_viewer/views.py @@ -252,6 +252,7 @@ def cached_get_labels(xpath): return response +@login_required def google_xls_export(request, username, id_string): owner = User.objects.get(username=username) xform = XForm.objects.get(id_string=id_string, user=owner) From 2b75fa77476af390568bfb17510dfad4a03d1a9a Mon Sep 17 00:00:00 2001 From: Larry Weya Date: Tue, 17 Apr 2012 14:53:23 +0300 Subject: [PATCH 04/20] Fixed duplicate sheet names causeing an error on xls export - Set xls sheet name lenght limit to 30, was 20 before will ask why - Added function to generate a unique name - Added test to make sure the function works --- odk_viewer/tests/__init__.py | 1 + odk_viewer/tests/test_exports.py | 13 +++++++++++++ odk_viewer/xls_writer.py | 26 ++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 odk_viewer/tests/test_exports.py diff --git a/odk_viewer/tests/__init__.py b/odk_viewer/tests/__init__.py index 1acf6cf18..991ea3fa2 100644 --- a/odk_viewer/tests/__init__.py +++ b/odk_viewer/tests/__init__.py @@ -2,3 +2,4 @@ from form_submission import TestFormSubmission from mongo_data_output import TestMongoData from test_map_view import TestMapView +from test_exports import TestExports diff --git a/odk_viewer/tests/test_exports.py b/odk_viewer/tests/test_exports.py new file mode 100644 index 000000000..2d95f634e --- /dev/null +++ b/odk_viewer/tests/test_exports.py @@ -0,0 +1,13 @@ +from main.tests.test_base import MainTestCase +from django.core.urlresolvers import reverse +from odk_logger.views import download_xlsform +from odk_viewer.xls_writer import XlsWriter + +class TestExports(MainTestCase): + def test_unique_xls_sheet_name(self): + xls_writer = XlsWriter() + xls_writer.add_sheet('section9_pit_latrine_with_slab_group') + xls_writer.add_sheet('section9_pit_latrine_without_slab_group') + # create a set of sheet names keys + sheet_names_set = set(xls_writer._sheets.keys()) + self.assertEqual(len(sheet_names_set), 2) diff --git a/odk_viewer/xls_writer.py b/odk_viewer/xls_writer.py index 0a908a00b..041a438e6 100644 --- a/odk_viewer/xls_writer.py +++ b/odk_viewer/xls_writer.py @@ -7,6 +7,7 @@ class XlsWriter(object): def __init__(self): self.set_file() self.reset_workbook() + self.sheet_name_limit = 30 def set_file(self, file_object=None): """ @@ -27,8 +28,11 @@ def one(): return 1 self._current_index = defaultdict(one) def add_sheet(self, name): - sheet = self._workbook.add_sheet(name[0:20]) - self._sheets[name] = sheet + # excel worksheet name limit seems to be 31 characters (30 to be safe) + unique_sheet_name = name[0:self.sheet_name_limit] + unique_sheet_name = self._generate_unique_sheet_name(unique_sheet_name) + sheet = self._workbook.add_sheet(unique_sheet_name) + self._sheets[unique_sheet_name] = sheet def add_column(self, sheet_name, column_name): index = len(self._columns[sheet_name]) @@ -98,3 +102,21 @@ def _add_sheets(self): if isinstance(f, Question) and\ not question_types_to_exclude(f.type): self.add_column(sheet_name, f.name) + + def _generate_unique_sheet_name(self, sheet_name): + # check if sheet name exists + if(not self._sheets.has_key(sheet_name)): + return sheet_name + else: + i = 1 + unique_name = sheet_name + while(self._sheets.has_key(unique_name)): + number_len = len(str(i)) + allowed_name_len = self.sheet_name_limit - number_len + # make name required len + if(len(unique_name) > allowed_name_len): + unique_name = unique_name[0:allowed_name_len] + unique_name = "{0}{1}".format(unique_name, i) + i = i + 1 + return unique_name + From f6c2d85f2bc599a6bd0a26e92ef5ba00b9f36c1a Mon Sep 17 00:00:00 2001 From: Larry Weya Date: Tue, 17 Apr 2012 15:28:38 +0300 Subject: [PATCH 05/20] Added a lokup dictionary for generated sheet names - Closes #234 --- odk_viewer/xls_writer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/odk_viewer/xls_writer.py b/odk_viewer/xls_writer.py index 041a438e6..b32e1070f 100644 --- a/odk_viewer/xls_writer.py +++ b/odk_viewer/xls_writer.py @@ -8,6 +8,7 @@ def __init__(self): self.set_file() self.reset_workbook() self.sheet_name_limit = 30 + self._generated_sheet_name_dict = {} def set_file(self, file_object=None): """ @@ -26,6 +27,7 @@ def reset_workbook(self): self._columns = defaultdict(list) def one(): return 1 self._current_index = defaultdict(one) + self._generated_sheet_name_dict = {} def add_sheet(self, name): # excel worksheet name limit seems to be 31 characters (30 to be safe) @@ -33,6 +35,7 @@ def add_sheet(self, name): unique_sheet_name = self._generate_unique_sheet_name(unique_sheet_name) sheet = self._workbook.add_sheet(unique_sheet_name) self._sheets[unique_sheet_name] = sheet + self._generated_sheet_name_dict[name] = unique_sheet_name def add_column(self, sheet_name, column_name): index = len(self._columns[sheet_name]) @@ -55,7 +58,8 @@ def add_obs(self, obs): self._fix_indices(obs) for sheet_name, rows in obs.items(): for row in rows: - self.add_row(sheet_name, row) + actual_sheet_name = self._generated_sheet_name_dict[sheet_name] + self.add_row(actual_sheet_name, row) def _fix_indices(self, obs): for sheet_name, rows in obs.items(): From a7c72cff3bb51a844cc1903d7c82e5aaab084b23 Mon Sep 17 00:00:00 2001 From: pld Date: Tue, 17 Apr 2012 10:12:26 -0400 Subject: [PATCH 06/20] consolidate renaming function, acomodate missing dict values, pass tests --- odk_viewer/xls_writer.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/odk_viewer/xls_writer.py b/odk_viewer/xls_writer.py index b32e1070f..91f7495ff 100644 --- a/odk_viewer/xls_writer.py +++ b/odk_viewer/xls_writer.py @@ -30,12 +30,9 @@ def one(): return 1 self._generated_sheet_name_dict = {} def add_sheet(self, name): - # excel worksheet name limit seems to be 31 characters (30 to be safe) - unique_sheet_name = name[0:self.sheet_name_limit] - unique_sheet_name = self._generate_unique_sheet_name(unique_sheet_name) + unique_sheet_name = self._unique_name_for_xls(name) sheet = self._workbook.add_sheet(unique_sheet_name) self._sheets[unique_sheet_name] = sheet - self._generated_sheet_name_dict[name] = unique_sheet_name def add_column(self, sheet_name, column_name): index = len(self._columns[sheet_name]) @@ -58,7 +55,8 @@ def add_obs(self, obs): self._fix_indices(obs) for sheet_name, rows in obs.items(): for row in rows: - actual_sheet_name = self._generated_sheet_name_dict[sheet_name] + actual_sheet_name = self._generated_sheet_name_dict.get( + sheet_name, sheet_name) self.add_row(actual_sheet_name, row) def _fix_indices(self, obs): @@ -74,7 +72,7 @@ def write_tables_to_workbook(self, tables): tables should be a list of pairs, the first element in the pair is the name of the table, the second is the actual data. - todo: figure out how to write to the xls file rather than keep + TODO: figure out how to write to the xls file rather than keep the whole workbook in memory. """ self.reset_workbook() @@ -107,6 +105,13 @@ def _add_sheets(self): not question_types_to_exclude(f.type): self.add_column(sheet_name, f.name) + def _unique_name_for_xls(self, sheet_name): + # excel worksheet name limit seems to be 31 characters (30 to be safe) + unique_sheet_name = sheet_name[0:self.sheet_name_limit] + unique_sheet_name = self._generate_unique_sheet_name(unique_sheet_name) + self._generated_sheet_name_dict[sheet_name] = unique_sheet_name + return unique_sheet_name + def _generate_unique_sheet_name(self, sheet_name): # check if sheet name exists if(not self._sheets.has_key(sheet_name)): From 207bb2e7322a27a40b88d7432ff42266f30ae7f7 Mon Sep 17 00:00:00 2001 From: pld Date: Tue, 17 Apr 2012 11:41:33 -0400 Subject: [PATCH 07/20] google site verification content key --- templates/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/base.html b/templates/base.html index 60b644379..611f6e856 100644 --- a/templates/base.html +++ b/templates/base.html @@ -5,6 +5,7 @@ formhub +