Beispiel #1
0
    def render_header(i, lang, **kwargs):
        """Render repeat group header.

        A repeat group header consists of some opening html tags, followed by
        an OdkPrompt with a few extra attributes.

        Args:
            i (dict): A dictionary row representing first row of repeat group.
            lang (str): The language.


            **kwargs: Keyword arguments.

        Returns:
            str: A rendered html representation of repeat group header.
        """
        # pylint: disable=no-member
        html = TEMPLATE_ENV.get_template(
            "content/repeat/repeat-opener.html").render(**kwargs,
                                                        settings=kwargs)
        i["simple_type"] = i["type"]
        i["in_repeat"] = True
        i["is_repeat_header"] = True
        html += OdkPrompt(i).to_html(lang, **kwargs, settings=kwargs)
        return html
Beispiel #2
0
 def test_question_number_field_statically(self):
     """Test that question numbers are geing generated as expected."""
     inputs_to_outputs = {
         "201. Random question": "201",
         "LCL_202. Random question": "LCL_202",
         "CRVS-203. Random question": "CRVS-203",
         "204.A. Random question": "204.A",
         "205.1. Random question": "205.1",
         "206.a. Random question": "206.a",
         "207.i. Random question": "207.i",
         "208.C.ii.1. Random question": "208.C.ii.1",
         "209.C.ii.1_v2. Random question": "209.C.ii.1_v2",
         "210.C.ii.1_v2-2. Random question": "210.C.ii.1_v2-2",
         "State: ${level1_unlinked}": "",
     }
     for k, v in inputs_to_outputs.items():
         prompt = {"label": k}
         question_number = OdkPrompt.extract_question_numbers(prompt)[
             "question_number"
         ]
         msg = (
             "Question number '{}' did not match what was "
             "expected for the following question: \n\n{}".format(question_number, k)
         )
         self.assertTrue(question_number == v, msg=msg)
Beispiel #3
0
    def to_html(self, lang, **kwargs):
        """Convert group components to html and return concatenation.

        Args:
            lang (str): The language.

        Returns:
            str: A rendered html concatenation of component templates.
        """
        html = ""
        # pylint: disable=no-member

        # - Render header
        html += TEMPLATE_ENV.get_template(
            "content/group/group-opener.html").render(**kwargs,
                                                      settings=kwargs)
        header = self.format_header(self.row)

        html += OdkPrompt(header).to_html(lang, **kwargs)

        # - Render body
        for i in self.data:
            row = i.data[0] if isinstance(i, OdkTable) else i
            if exclusion(item=row, settings=kwargs):
                continue

            if isinstance(i, OdkPrompt):
                i.row["in_repeat"] = self.in_repeat
                i.row["in_group"] = True
                html += i.to_html(lang, **kwargs)
            elif isinstance(i, OdkTable):
                i.in_repeat = self.in_repeat
                html += i.to_html(lang, **kwargs)

        # - Render footer
        # pylint: disable=no-member
        html += TEMPLATE_ENV.get_template(
            "content/group/group-closer.html").render(**kwargs,
                                                      settings=kwargs)

        return html
Beispiel #4
0
    def to_html(self, lang, highlighting, **kwargs):
        """Convert group components to html and return concatenation.

        Args:
            lang (str): The language.
            highlighting (bool): For color highlighting of various components
                of html template.

        Returns:
            str: A rendered html concatenation of component templates.
        """
        html = ''
        # pylint: disable=no-member

        # - Render header
        html += TEMPLATE_ENV.get_template('content/group/group-opener.html')\
            .render(**kwargs)
        header = self.format_header(self.opener)

        html += OdkPrompt(header).to_html(lang, highlighting, **kwargs)

        # - Render body
        for i in self.data:
            if exclusion(item=i, settings=kwargs):
                continue

            if isinstance(i, OdkPrompt):
                i.row['in_repeat'] = self.in_repeat
                i.row['in_group'] = True
                html += i.to_html(lang, highlighting, **kwargs)
            elif isinstance(i, OdkTable):
                i.in_repeat = self.in_repeat
                html += i.to_html(lang, highlighting, **kwargs)

        # - Render footer
        # pylint: disable=no-member
        html += TEMPLATE_ENV.get_template('content/group/group-closer.html')\
            .render(**kwargs)

        return html
Beispiel #5
0
    def _add_question_iter_nums(obj, data={"qnum": "", "i": 0}, depth=0):
        """Add iteration numbers to unique question prompts.

        Possible improvements: Make it so that this doesn't depend on
        OdkPrompt._extract_question_numbers.

        Args:
            obj (list): From either: OdkForm.questionnaire (a list of objects
            representing form components.), OdkGroup.row, or OdkRepeat.row.
            data (dict): Running data. Tracks current question number 'qnum'
            and also current iteration 'i'. The 'i' should increment by 1 for
            each new question number. In this case, a question number is
            rigidly considered "new" if it is not exactly equal to whatever
            was considered to be the immediately preceding question number
            in the form.
            depth (int): Recursion depth. Starts at 0. Increments by 1 each
            time this function recurses, which happens every time an OdkRepeat
            or OdkGroup is encountered.

        Returns:
            list: OdkForm.questionnaire with new 'i' values included.
        """
        for i, element in enumerate(obj):
            if any(
                    isinstance(element, x)
                    for x in (OdkRepeat, OdkGroup, OdkTable)):
                element.data, data = OdkForm._add_question_iter_nums(
                    element.data, data, depth + 1)
            elif isinstance(element, OdkPrompt):
                element.row = OdkPrompt.extract_question_numbers(element.row)
                qnum = element.row["question_number"]
                if qnum not in (data["qnum"], ""):
                    data["i"] += 1
                    data["qnum"] = qnum
                element.row["i"] = data["i"]
            elif isinstance(element, OdkCalculate):
                element.row["i"] = data["i"]
        if depth == 0:
            return obj
        return obj, data
Beispiel #6
0
 def test_question_number_field_statically(self):
     """Test that question numbers are geing generated as expected."""
     inputs_to_outputs = {
         '201. Random question': '201',
         'LCL_202. Random question': 'LCL_202',
         'CRVS-203. Random question': 'CRVS-203',
         '204.A. Random question': '204.A',
         '205.1. Random question': '205.1',
         '206.a. Random question': '206.a',
         '207.i. Random question': '207.i',
         '208.C.ii.1. Random question': '208.C.ii.1',
         '209.C.ii.1_v2. Random question': '209.C.ii.1_v2',
         '210.C.ii.1_v2-2. Random question': '210.C.ii.1_v2-2',
         'State: ${level1_unlinked}': ''
     }
     for k, v in inputs_to_outputs.items():
         prompt = {'label': k}
         question_number = \
             OdkPrompt.extract_question_numbers(prompt)['question_number']
         msg = 'Question number \'{}\' did not match what was ' \
               'expected for the following question: \n\n{}'\
             .format(question_number, k)
         self.assertTrue(question_number == v, msg=msg)
Beispiel #7
0
    def render_header(i, lang, highlighting, **kwargs):
        """Render repeat group header.

        A repeat group header consists of some opening html tags, followed by
        an OdkPrompt with a few extra attributes.

        Args:
            i (dict): A dictionary row representing first row of repeat group.
            lang (str): The language.
            highlighting (bool): For color highlighting of various components
                of html template.
            **kwargs: Keyword arguments.

        Returns:
            str: A rendered html representation of repeat group header.
        """
        # pylint: disable=no-member
        html = TEMPLATE_ENV.get_template('content/repeat/repeat-opener.html')\
            .render()
        i['simple_type'] = i['type']
        i['in_repeat'] = True
        i['is_repeat_header'] = True
        html += OdkPrompt(i).to_html(lang, highlighting, **kwargs)
        return html
Beispiel #8
0
    def convert_survey(wb, choices, ext_choices):
        """Convert rows and strings of a workbook into object components.

        Main types are:

        - prompt
        - calculate
        - begin group
        - end group
        - begin repeat
        - end repeat
        - table
        - context group (group without field-list appearance)

        Args:
            wb (Xlsform): A Xlsform object representing an XLSForm.

        Returns:
            list: A list of objects representing form components.

        Raises:
            OdkformError: Handle several errors, including: mismatched groups
                or repeat groups, errors when appending to groups or repeat
                groups, erroneously formed tables, duplicate context group
                names, and groups nested within a field-list group.
        """
        context = OdkForm.ConversionContext()
        survey, header = None, None
        try:
            survey = wb["survey"]
            header = survey[0]
        except KeyError:  # No survey found.
            pass

        if survey and header:
            for i, row in enumerate(survey):
                if i == 0:
                    continue
                dict_row = {str(k): str(v) for k, v in zip(header, row)}
                token = OdkForm.parse_type(dict_row, choices, ext_choices)

                if token["token_type"] == "prompt":
                    dict_row["simple_type"] = token["simple_type"]
                    choice_list = token["choice_list"]
                    this_prompt = OdkPrompt(dict_row, choice_list)
                    context.add_prompt(this_prompt)
                elif token["token_type"] == "calculate":
                    dict_row["simple_type"] = token["simple_type"]
                    this_calculate = OdkCalculate(dict_row)
                    context.add_calculate(this_calculate)
                elif token["token_type"] == "begin group":
                    this_group = OdkGroup(dict_row)
                    context.add_group(this_group)
                elif token["token_type"] == "context group":
                    # Possibly make an OdkGroup here...
                    context.add_context_group()
                elif token["token_type"] == "end group":
                    context.end_group()
                elif token["token_type"] == "begin repeat":
                    this_repeat = OdkRepeat(dict_row)
                    context.add_repeat(this_repeat)
                elif token["token_type"] == "end repeat":
                    context.end_repeat()
                elif token["token_type"] == "table":
                    dict_row["simple_type"] = token["simple_type"]
                    choice_list = token["choice_list"]
                    this_prompt = OdkPrompt(dict_row, choice_list)
                    context.add_table(this_prompt)
                elif token["token_type"] == "custom":
                    this_custom = OdkCustomType(dict_row)
                    context.add_custom_type(this_custom)
                else:
                    # TODO: Make an error?
                    pass

        return context.result