Beispiel #1
0
def expand_choices(tree, params, include_path):
    rows = []

    for command, *args in tree:
        if command == "#":
            continue

        if command == "@":
            if args[0] == "include":
                rows.extend(
                    execute_include(filename=args[1],
                                    args=args[2:],
                                    params=copy.deepcopy(params),
                                    include_path=include_path))
            else:
                raise NameError(f"Unknown command: @{args[0]}.")
        elif command == "list":
            list_params = merge_params(params, {"list_name": args[0]})

            list_params.update(args_to_params(args[1]))

            rows.extend(expand_choices(args[2], list_params, include_path))
        else:
            rows.append(compile_choice(command, args, copy.deepcopy(params)))

    return rows
Beispiel #2
0
def execute_include(filename, args, params, include_path):
    """Generate entries for the 'choices' worksheet based on an
    @include command."""

    include_path, filename = new_path_and_filename(include_path, filename)

    include_macros = args_to_params(args)

    with open(filename) as f:
        return expand_choices(
            parse_choices().parseString(substitute_macros(
                f.read(), include_macros),
                                        parseAll=True).asList(), params,
            include_path)
Beispiel #3
0
def execute_form_settings(form_id, form_version, form_title, args):
    "Generate the 'settings' worksheet based on a @form command."

    form_settings = {"form_title": form_title,
                     "form_id": form_id}
    form_settings.update(
        args_to_params(args))

    if form_version == "auto":
        form_settings["version"] = (
            datetime.datetime.utcnow()
            .strftime("%y%m%d%H%M"))
    else:
        form_settings["version"] = form_version

    return form_settings
Beispiel #4
0
def execute_choices(filename, args, include_path):
    "Generate a choice list based on a @choices command."

    include_path, filename = new_path_and_filename(
        include_path, filename)

    choices_macros = args_to_params(args)

    with open(filename) as f:
        return expand_choices(
            parse_choices().parseString(
                substitute_macros(
                    f.read(),
                    choices_macros),
                parseAll=True).asList(),
            dict(),
            include_path)
Beispiel #5
0
def compile_question(name, args, params):
    "Compile a question for the 'survey' worksheet."

    question = {"name": name,
                "type": " ".join(str(word) for word in args[0])}

    if len(args) % 2 == 1:
        question_params = args[1:]
    else:
        if question["type"] == "calculate":
            question["calculation"] = args[1]
        else:
            question["label"] = args[1]

        question_params = args[2:]

    question.update(
        merge_params(
            params, args_to_params(question_params)))

    return question
Beispiel #6
0
def execute_include(filename, args, params, include_path):
    """Generate 'survey' and 'choices' worksheets based on an
    @include command."""

    include_path, filename = new_path_and_filename(
        include_path, filename)

    include_macros = args_to_params(args)

    with open(filename) as f:
        try:
            include_tree = parse_survey().parseString(
                               preprocess_indent(
                                   substitute_macros(
                                       f.read(),
                                       include_macros)),
                               parseAll=True).asList()
        except pp.ParseException:
            raise ValueError(
                f"Error when parsing {filename}.")

    return expand_survey(include_tree, params, include_path)
Beispiel #7
0
def compile_choice(value, args, params):
    choice = {"value": value, "label": args[0]}

    choice.update(merge_params(params, args_to_params(args[1:])))

    return choice
Beispiel #8
0
def expand_survey(tree, params, include_path):
    rows = []
    choices = []
    settings = None

    for command, *args in tree:
        if command == "#":
            continue

        if command == "@":
            if args[0] == "form":
                settings = [
                    execute_form_settings(
                        form_id=args[1],
                        form_version=args[2],
                        form_title=args[3],
                        args=args[4:])]
            elif args[0] == "choices":
                choices.extend(
                    execute_choices(
                        filename=args[1],
                        args=args[2:],
                        include_path=include_path))
            elif args[0] == "include":
                included_survey = execute_include(
                    filename=args[1],
                    args=args[2:],
                    params=copy.deepcopy(params),
                    include_path=include_path)

                rows.extend(included_survey.survey)
                choices.extend(included_survey.choices)
            elif args[0] == "required":
                params["required"] = args[1]
            else:
                raise NameError(f"Unknown command: @{args[0]}.")
        elif command == "if":
            if_params = merge_params(
                params,
                {"relevance": if_cond_to_relevance(args[0])})

            expanded = expand_survey(
                args[1], if_params, include_path)
            rows.extend(expanded.survey)
        elif command in ("group", "repeat"):
            group_name = args[0][0]
            group_def = {
                "type": f"begin {command}",
                "name": group_name
            }

            if len(args[0]) > 1:
                group_def["label"] = args[0][1]

            group_params = merge_params(
                params, args_to_params(args[1]))

            rows.append({**group_def, **group_params})

            for param_name in ("relevance", "appearance"):
                if param_name in group_params:
                    del group_params[param_name]

            expanded = expand_survey(
                args[2], group_params, include_path)
            rows.extend(expanded.survey)

            rows.append(
                {"type": f"end {command}",
                 "name": group_name})
        else:
            rows.append(
                compile_question(
                    command, args, copy.deepcopy(params)))

    return namedtuple("Survey", ("survey", "choices", "settings"))(
        survey=rows,
        choices=choices,
        settings=settings)