Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include check to throw error if external choices list is not found #339

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyxform/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
# The following are the possible sheet names:
SURVEY = "survey"
SETTINGS = "settings"
EXTERNAL_CHOICES = "external_choices"
# These sheet names are for list sheets
CHOICES_AND_COLUMNS = "choices and columns"
CASCADING_CHOICES = "cascades"
Expand All @@ -84,6 +85,7 @@
COLUMNS,
CHOICES_AND_COLUMNS,
SETTINGS,
EXTERNAL_CHOICES,
OSM,
]
SUPPORTED_FILE_EXTENSIONS = [".xls", ".xlsx", ".xlsm"]
Expand Down
49 changes: 49 additions & 0 deletions pyxform/tests_v1/test_support_external_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,52 @@ def test_non_existent_itext_reference(self):
</itemset>"""
],
)

def test_external_choices_sheet_values_required(self):
md = """
| survey | | | | |
| | type | name | label | choice_filter |
| | text | S1 | s1 | |
| | select_one_external counties | county | county | S1=${S1} |
| | select_one_external cities | city | city | S1=${S1} and county=${county} |
| choices | | | |
| | list name | name | label |
| | list | option a | a |
| external_choices | | |
| | list_name | name |
| | counties | Kajiado |
| | counties | Nakuru |
| | cities | Kisumu |
| | cities | Mombasa |
"""
expected = [
"""<itemset nodeset="instance('cities')/root/item">
<value ref="name"/>
<label ref="label"/>
</itemset>"""
] # noqa
self.assertPyxformXform(
md=md, debug=True, model__contins=[expected], run_odk_validate=True
)

def test_list_name_not_in_external_choices_sheet_raises_error(self):
self.assertPyxformXform(
md="""
| survey | | | | |
| | type | name | label | choice_filter |
| | select_one list | S1 | s1 | |
| | select_one_external counties | county | County | S1=${S1} |
| | select_one_external cities | city | City | S1=${S1} and county=${county} |
| choices | | | |
| | list name | name | label |
| | list | option a | a |
| | list | option b | b |
| | list | option c | c |
| external_choices | | |
| | list_name | name |
| | counties | Kajiado |
| | counties | Nakuru |
""", # noqa
errored=True,
error__contains=["List name not in external choices sheet: cities"],
)
25 changes: 23 additions & 2 deletions pyxform/xls2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,19 @@ def workbook_to_json(
# Here the default settings are overridden by those in the settings sheet
json_dict.update(settings)

# ########## External Choices sheet ##########

external_choices_sheet = workbook_dict.get(constants.EXTERNAL_CHOICES, [])
for choice_item in external_choices_sheet:
replace_smart_quotes_in_dict(choice_item)

external_choices_sheet = dealias_and_group_headers(
external_choices_sheet, aliases.list_header, use_double_colons, default_language
)
external_choices = group_dictionaries_by_key(
external_choices_sheet, constants.LIST_NAME
)

# ########## Choices sheet ##########
# Columns and "choices and columns" sheets are deprecated,
# but we combine them with the choices sheet for backwards-compatibility.
Expand Down Expand Up @@ -998,10 +1011,18 @@ def replace_prefix(d, prefix):
+ " select one external is only meant for"
" filtered selects."
)
select_type = aliases.select["select_one"]
list_name = parse_dict["list_name"]
list_file_name, file_extension = os.path.splitext(list_name)

if (
select_type == "select one external"
and list_name not in external_choices
):
raise PyXFormError(
row_format_string % row_number
+ "List name not in external choices sheet: "
+ list_name
)
select_type = aliases.select["select_one"]
if (
list_name not in choices
and select_type != "select one external"
Expand Down