Skip to content

Commit

Permalink
Merge pull request #666 from lindsay-stevens/pyxform-653
Browse files Browse the repository at this point in the history
#653 Detection of multilanguage choices only works if first choice list is multilanguage
  • Loading branch information
lognaturel authored Dec 1, 2023
2 parents efd4768 + 05ad654 commit ee6bd2d
Show file tree
Hide file tree
Showing 15 changed files with 442 additions and 188 deletions.
12 changes: 7 additions & 5 deletions pyxform/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ def __init__(self, **kwargs):
# I don't know why we would need an explicit none option for
# select alls
self._add_none_option = False
self._sections: Optional[Dict[str, Dict]] = None
self.set_sections(kwargs.get("sections", {}))

# dictionary of setvalue target and value tuple indexed by triggering element
self.setvalues_by_triggering_ref = {}
# For tracking survey-level choices while recursing through the survey.
self.choices: Dict[str, Any] = {}
self._choices: Dict[str, Any] = {}

def set_sections(self, sections):
"""
Expand All @@ -112,13 +113,13 @@ def create_survey_element_from_dict(

if d[const.TYPE] in self.SECTION_CLASSES:
if d[const.TYPE] == const.SURVEY:
self.choices = copy.deepcopy(d.get(const.CHOICES, {}))
self._choices = copy.deepcopy(d.get(const.CHOICES, {}))

section = self._create_section_from_dict(d)

if d[const.TYPE] == const.SURVEY:
section.setvalues_by_triggering_ref = self.setvalues_by_triggering_ref
section.choices = self.choices
section.choices = self._choices

return section
elif d[const.TYPE] == const.LOOP:
Expand Down Expand Up @@ -263,7 +264,7 @@ def _create_section_from_dict(self, d):
survey_element = self.create_survey_element_from_dict(copy.deepcopy(child))
if child[const.TYPE].endswith(const.SELECT_OR_OTHER_SUFFIX):
select_question = survey_element[0]
itemset_choices = self.choices.get(select_question[const.ITEMSET], None)
itemset_choices = self._choices.get(select_question[const.ITEMSET], None)
if (
itemset_choices is not None
and isinstance(itemset_choices, list)
Expand Down Expand Up @@ -307,7 +308,8 @@ def _create_loop_from_dict(self, d):
# TODO: Verify that nothing breaks if this returns a list
return result.children

def _name_and_label_substitutions(self, question_template, column_headers):
@staticmethod
def _name_and_label_substitutions(question_template, column_headers):
# if the label in column_headers has multiple languages setup a
# dictionary by language to do substitutions.
info_by_lang = {}
Expand Down
2 changes: 2 additions & 0 deletions pyxform/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
SELECT_ALL_THAT_APPLY = "select all that apply"
SELECT_OR_OTHER_SUFFIX = " or specify other"
RANK = "rank"
QUESTION = "question"
CHOICE = "choice"
CHOICES = "choices"

# XLS Specific constants
Expand Down
8 changes: 4 additions & 4 deletions pyxform/entities/entities_parsing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, List
from typing import Any, Dict, List

from pyxform import constants as const
from pyxform.errors import PyXFormError
Expand All @@ -8,8 +8,8 @@


def get_entity_declaration(
entities_sheet: Dict, workbook_dict: Dict, warnings: List
) -> Dict:
entities_sheet: List[Dict], workbook_dict: Dict[str, List[Dict]], warnings: List[str]
) -> Dict[str, Any]:
if len(entities_sheet) == 0:
similar = find_sheet_misspellings(key=const.ENTITIES, keys=workbook_dict.keys())
if similar is not None:
Expand Down Expand Up @@ -82,7 +82,7 @@ def get_validated_dataset_name(entity):


def validate_entity_saveto(
row: Dict, row_number: int, entity_declaration: Dict, in_repeat: bool
row: Dict, row_number: int, entity_declaration: Dict[str, Any], in_repeat: bool
):
save_to = row.get(const.BIND, {}).get("entities:saveto", "")
if not save_to:
Expand Down
15 changes: 0 additions & 15 deletions pyxform/instance_info.py

This file was deleted.

31 changes: 13 additions & 18 deletions pyxform/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@
from pyxform.errors import PyXFormError
from pyxform.question_type_dictionary import QUESTION_TYPE_DICT
from pyxform.survey_element import SurveyElement
from pyxform.utils import (
PYXFORM_REFERENCE_REGEX,
default_is_dynamic,
has_dynamic_label,
node,
)
from pyxform.utils import PYXFORM_REFERENCE_REGEX, default_is_dynamic, node


class Question(SurveyElement):
FIELDS = SurveyElement.FIELDS.copy()
FIELDS.update(
{
"_itemset_multi_language": bool,
"_itemset_has_media": bool,
"_itemset_dyn_label": bool,
}
)

def validate(self):
SurveyElement.validate(self)

Expand Down Expand Up @@ -202,12 +206,6 @@ def build_xml(self):
for element in self.xml_label_and_hint():
result.appendChild(element)

choices = survey.get("choices")
multi_language = False
if choices is not None and len(choices) > 0:
first_choices = next(iter(choices.values()))
multi_language = isinstance(first_choices[0].get("label"), dict)

# itemset are only supposed to be strings,
# check to prevent the rare dicts that show up
if self["itemset"] and isinstance(self["itemset"], str):
Expand All @@ -227,16 +225,13 @@ def build_xml(self):
else EXTERNAL_CHOICES_ITEMSET_REF_LABEL,
)

has_media = False
has_dyn_label = False
multi_language = self.get("_itemset_multi_language", False)
has_media = self.get("_itemset_has_media", False)
has_dyn_label = self.get("_itemset_dyn_label", False)
is_previous_question = bool(
PYXFORM_REFERENCE_REGEX.search(self.get("itemset"))
)

if choices.get(itemset):
has_media = bool(choices[itemset][0].get("media"))
has_dyn_label = has_dynamic_label(choices[itemset], multi_language)

if file_extension in EXTERNAL_INSTANCE_EXTENSIONS:
itemset = itemset
else:
Expand Down
Loading

0 comments on commit ee6bd2d

Please sign in to comment.