From c43fc43df57136c1134b9e7de1e6409d177a2679 Mon Sep 17 00:00:00 2001 From: Joshua Beretta Date: Wed, 2 Jun 2021 16:19:52 +0000 Subject: [PATCH 1/4] handle choice list_name as pyxform variable --- src/formpack/schema/fields.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/formpack/schema/fields.py b/src/formpack/schema/fields.py index 2356f86f..59911f2e 100644 --- a/src/formpack/schema/fields.py +++ b/src/formpack/schema/fields.py @@ -157,7 +157,11 @@ def from_json_definition(cls, definition, hierarchy=None, if data_type in ('select_one', 'select_multiple'): choice_id = definition['select_from_list_name'] - choice = field_choices[choice_id] + # pyxform#472 introduced dynamic list_names for select_one with the + # format of `select_one ${question_name}`. The choices are + # therefore not within a separate choice list + if not choice_id.startswith('$'): + choice = field_choices[choice_id] data_type_classes = { # selects From 8e2d9d33b448067404fc8653094c80b2457ea849 Mon Sep 17 00:00:00 2001 From: Joshua Beretta Date: Wed, 2 Jun 2021 17:54:49 +0000 Subject: [PATCH 2/4] add test and fixtures for select one from previous answers --- .../__init__.py | 19 +++++ .../select_one_from_previous_answers/v1.json | 76 +++++++++++++++++++ tests/test_exports.py | 57 ++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 tests/fixtures/select_one_from_previous_answers/__init__.py create mode 100644 tests/fixtures/select_one_from_previous_answers/v1.json diff --git a/tests/fixtures/select_one_from_previous_answers/__init__.py b/tests/fixtures/select_one_from_previous_answers/__init__.py new file mode 100644 index 00000000..58738e18 --- /dev/null +++ b/tests/fixtures/select_one_from_previous_answers/__init__.py @@ -0,0 +1,19 @@ +# coding: utf-8 + +from __future__ import (unicode_literals, print_function, + absolute_import, division) + +''' +select_one_from_previous_answers + +''' + +from ..load_fixture_json import load_fixture_json + +DATA = { + 'title': 'Household survey with select_one from previous answers', + 'id_string': 'select_one_from_previous_answers', + 'versions': [ + load_fixture_json('select_one_from_previous_answers/v1'), + ], +} diff --git a/tests/fixtures/select_one_from_previous_answers/v1.json b/tests/fixtures/select_one_from_previous_answers/v1.json new file mode 100644 index 00000000..06116291 --- /dev/null +++ b/tests/fixtures/select_one_from_previous_answers/v1.json @@ -0,0 +1,76 @@ +{ + "version": "romev1", + "content": { + "survey": [ + { + "name": "Q1", + "type": "integer", + "label": [ + "How many members live in your family?" + ] + }, + { + "name": "FM", + "type": "begin_repeat", + "label": [ + "Family Members" + ], + "repeat_count": "${Q1}" + }, + { + "name": "Q2", + "type": "text", + "label": [ + "Name?" + ] + }, + { + "name": "Q3", + "type": "integer", + "label": [ + "${Q2}'s age?" + ] + }, + { + "type": "end_repeat" + }, + { + "name": "Q4", + "type": "select_one", + "label": [ + "Select the head of the household." + ], + "select_from_list_name": "${Q2}" + }, + { + "name": "Q5", + "type": "select_one", + "label": [ + "Select the youngest child (<18 years) who is currently available in the family." + ], + "choice_filter": "${Q3} < 18", + "select_from_list_name": "${Q2}" + } + ] + }, + "submissions": [ + { + "FM": [ + { + "FM/Q2": "Julius Caesar", + "FM/Q3": "53" + }, + { + "FM/Q2": "Gaius Octavius", + "FM/Q3": "17" + } + ], + "FM_count": "2", + "Q1": "2", + "Q4": "Julius Caesar", + "Q5": "Gaius Octavius", + "meta/versionID": "romev1", + "meta/instanceID": "uuid:40805f86-2638-46f1-ab5a-72f4632474b5" + } + ] +} diff --git a/tests/test_exports.py b/tests/test_exports.py index b4b9f0d5..8d41f30b 100644 --- a/tests/test_exports.py +++ b/tests/test_exports.py @@ -415,6 +415,63 @@ def test_repeats(self): ]) ) + def test_select_one_from_previous_answers(self): + title, schemas, submissions = build_fixture( + 'select_one_from_previous_answers' + ) + fp = FormPack(schemas, title) + options = {'versions': 'romev1'} + export = fp.export(**options).to_dict(submissions) + expected_dict = OrderedDict( + [ + ( + 'Household survey with select_one from previous answers', + { + 'fields': [ + 'Q1', + 'Q4', + 'Q5', + '_index', + ], + 'data': [ + [ + '2', + 'Julius Caesar', + 'Gaius Octavius', + 1, + ] + ], + }, + ), + ( + 'FM', + { + 'fields': [ + 'Q2', + 'Q3', + '_parent_table_name', + '_parent_index', + ], + 'data': [ + [ + 'Julius Caesar', + '53', + 'Household survey with select_one from previous answers', + 1, + ], + [ + 'Gaius Octavius', + '17', + 'Household survey with select_one from previous answers', + 1, + ], + ], + }, + ), + ] + ) + self.assertEqual(export, expected_dict) + def test_nested_repeats_with_copy_fields(self): title, schemas, submissions = build_fixture( 'nested_grouped_repeatable') From b4e5abe0d6218304bd63836ca41d2e009b9407d9 Mon Sep 17 00:00:00 2001 From: Alex Dorey Date: Thu, 17 Jun 2021 13:53:47 -0400 Subject: [PATCH 3/4] added a little specificity and clarity --- src/formpack/schema/fields.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/formpack/schema/fields.py b/src/formpack/schema/fields.py index 59911f2e..ba6bcca6 100644 --- a/src/formpack/schema/fields.py +++ b/src/formpack/schema/fields.py @@ -160,7 +160,10 @@ def from_json_definition(cls, definition, hierarchy=None, # pyxform#472 introduced dynamic list_names for select_one with the # format of `select_one ${question_name}`. The choices are # therefore not within a separate choice list - if not choice_id.startswith('$'): + if choice_id.startswith('${') and choice_id.endswith('}'): + # ${dynamic_choice}, so question will be treated as a TextField + choice = None + else: choice = field_choices[choice_id] data_type_classes = { From cf673f02ada6f7fd419b97e52f11a17419c05651 Mon Sep 17 00:00:00 2001 From: Alex Dorey Date: Thu, 17 Jun 2021 14:16:24 -0400 Subject: [PATCH 4/4] avoiding setting choice value twice --- src/formpack/schema/fields.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/formpack/schema/fields.py b/src/formpack/schema/fields.py index ba6bcca6..cfa6881f 100644 --- a/src/formpack/schema/fields.py +++ b/src/formpack/schema/fields.py @@ -150,7 +150,6 @@ def from_json_definition(cls, definition, hierarchy=None, # normalize spaces data_type = definition['type'] - choice = None if ' ' in data_type: raise ValueError('invalid data_type: %s' % data_type) @@ -165,6 +164,8 @@ def from_json_definition(cls, definition, hierarchy=None, choice = None else: choice = field_choices[choice_id] + else: + choice = None data_type_classes = { # selects