Skip to content

Commit 6c4970b

Browse files
committed
fix: ensure choices/option parent is set correctly
1 parent 854ffe6 commit 6c4970b

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

pyxform/question.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
XForm Survey element classes for different question types.
33
"""
44

5+
import copy
56
import os.path
67
from collections.abc import Callable, Generator, Iterable
78
from itertools import chain
@@ -372,7 +373,7 @@ def __init__(
372373
kw_children = kwargs.pop(constants.CHILDREN, None)
373374
choices = coalesce(kw_choices, kw_children)
374375
if isinstance(choices, tuple) and isinstance(next(iter(choices)), Option):
375-
self.children = choices
376+
self.children = copy.deepcopy(choices)
376377
elif choices:
377378
self.children = tuple(
378379
Option(**c) for c in combine_lists(kw_choices, kw_children)

tests/test_builder.py

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
from unittest import TestCase
99

1010
import defusedxml.ElementTree as ETree
11-
from pyxform import InputQuestion, Survey
12-
from pyxform.builder import SurveyElementBuilder, create_survey_from_xls
11+
from pyxform import InputQuestion, MultipleChoiceQuestion, Survey
12+
from pyxform.builder import (
13+
SurveyElementBuilder,
14+
create_survey_element_from_dict,
15+
create_survey_from_xls,
16+
)
1317
from pyxform.errors import PyXFormError
18+
from pyxform.question import Option
1419
from pyxform.xls2json import print_pyobj_to_json
1520

1621
from tests import utils
@@ -562,3 +567,120 @@ def test_style_added_to_body_if_present(self):
562567
]
563568
self.assertEqual(len(body_elms), 1)
564569
self.assertEqual(body_elms[0].get("class"), "ltr")
570+
571+
def test_options_has_correct_parent(self):
572+
survey_dict = {
573+
"type": "survey",
574+
"name": "data",
575+
"title": "empty_cell",
576+
"id_string": "empty_cell",
577+
"sms_keyword": "empty_cell",
578+
"default_language": "default",
579+
"children": [
580+
{
581+
"type": "group",
582+
"name": "a",
583+
"label": "Group A",
584+
"children": [
585+
{
586+
"type": "select one",
587+
"name": "fruita",
588+
"label": "Fruit A",
589+
"parameters": {},
590+
"itemset": "fruits",
591+
"list_name": "fruits",
592+
"choices": [
593+
{"name": "orange", "label": "Orange"},
594+
{"name": "mango", "label": "Mango"},
595+
],
596+
},
597+
{
598+
"type": "select one",
599+
"name": "fruity",
600+
"label": "Fruit Y",
601+
"parameters": {},
602+
"itemset": "fruity",
603+
"list_name": "fruity",
604+
"choices": [
605+
{"name": "orange", "label": "Orange"},
606+
{"name": "mango", "label": "Mango"},
607+
],
608+
},
609+
],
610+
},
611+
{
612+
"type": "group",
613+
"name": "b",
614+
"label": "Group B",
615+
"children": [
616+
{
617+
"type": "select one",
618+
"name": "fruitz",
619+
"label": "Fruit Z",
620+
"parameters": {},
621+
"itemset": "fruits",
622+
"list_name": "fruits",
623+
"choices": [
624+
{"name": "orange", "label": "Orange"},
625+
{"name": "mango", "label": "Mango"},
626+
],
627+
},
628+
{
629+
"type": "select all that apply",
630+
"name": "fruitb",
631+
"label": "Fruit B",
632+
"parameters": {},
633+
"itemset": "fruity",
634+
"list_name": "fruity",
635+
"choices": [
636+
{"name": "orange", "label": "Orange"},
637+
{"name": "mango", "label": "Mango"},
638+
],
639+
},
640+
],
641+
},
642+
{
643+
"name": "meta",
644+
"type": "group",
645+
"control": {"bodyless": True},
646+
"children": [
647+
{
648+
"name": "instanceID",
649+
"bind": {"readonly": "true()", "jr:preload": "uid"},
650+
"type": "calculate",
651+
}
652+
],
653+
},
654+
],
655+
"choices": {
656+
"fruits": [
657+
{"name": "orange", "label": "Orange"},
658+
{"name": "mango", "label": "Mango"},
659+
],
660+
"fruity": [
661+
{"name": "orange", "label": "Orange"},
662+
{"name": "mango", "label": "Mango"},
663+
],
664+
},
665+
}
666+
survey = create_survey_element_from_dict(survey_dict)
667+
668+
fruita = survey.children[0].children[0]
669+
self.assertTrue(isinstance(fruita, MultipleChoiceQuestion))
670+
self.assertEqual(fruita.name, "fruita")
671+
672+
fruita_orange = fruita.children[0]
673+
self.assertTrue(isinstance(fruita_orange, Option))
674+
self.assertEqual(fruita_orange.name, "orange")
675+
self.assertEqual(fruita_orange.parent, fruita)
676+
self.assertEqual(fruita_orange.get_xpath(), "/data/a/fruita/orange")
677+
678+
fruitz = survey.children[1].children[0]
679+
self.assertTrue(isinstance(fruitz, MultipleChoiceQuestion))
680+
self.assertEqual(fruitz.name, "fruitz")
681+
682+
fruitz_orange = fruitz.children[0]
683+
self.assertTrue(isinstance(fruitz_orange, Option))
684+
self.assertEqual(fruitz_orange.name, "orange")
685+
self.assertEqual(fruitz_orange.parent, fruitz)
686+
self.assertEqual(fruitz_orange.get_xpath(), "/data/b/fruitz/orange")

0 commit comments

Comments
 (0)