diff --git a/src/formpack/schema/fields.py b/src/formpack/schema/fields.py index 2356f86f..cfa6881f 100644 --- a/src/formpack/schema/fields.py +++ b/src/formpack/schema/fields.py @@ -150,14 +150,22 @@ 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) 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 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] + else: + choice = None data_type_classes = { # selects 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')