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
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)
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
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
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
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)
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
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