Система шаблонов Django для генерации запускаемых программ

Я рассматриваю возможность использования системы шаблонов Django для довольно необычного случая использования и ищу некоторые рекомендации.

У меня есть приложение, которое позволяет пользователям решать проблемы программирования, представляя кодовое решение. Приложение позволяет пользователям писать программы на нескольких языках, включая Python, JS/TS и C.

Каждая задача связана с набором тестовых примеров, предназначенных для проверки правильности представленного решения. Мое приложение объединяет пользовательский код и код тестовых примеров в программу, которая выполняется в изолированной среде.

<
def get_testcase_execution_block(
    testcase: ExerciseTestCase, execution_results_list_identifier: str
) -> str:
    results_dict = get_random_identifier()
    exception_identifier = get_random_identifier()
    return (
        f"try:\n"
        + f"    {testcase.code}\n"
        + f"    {results_dict} = {{'passed': True, 'id': {testcase.pk}}}\n"
        + f"except Exception as {exception_identifier}:\n"
        + f"    ex_type, ex_value, ex_traceback = sys.exc_info()\n"
        + f"    trace_back = traceback.extract_tb(ex_traceback)\n"
        + f"    stack_trace = list()\n"
        + f"    for trace in trace_back:\n"
        + f'        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))\n'
        + f"    {results_dict} = {{'passed': False, 'id': {testcase.pk}, 'error': ex_type.__name__ + ': ' + str(ex_value) + ' (' + str(stack_trace) +')'}}\n"
        + f"{execution_results_list_identifier}.append({results_dict})\n"
    )


def get_python_program_for_vm(code: str, testcases: ExerciseTestCase) -> str:
    execution_results_list_identifier = get_random_identifier()
    testcases_str = "".join(
        [
            get_testcase_execution_block(t, execution_results_list_identifier)
            for t in testcases
        ]
    )
    return (
        "import sys\n"
        + "import traceback\n"
        + "import json\n"
        + f"{execution_results_list_identifier}=[]\n"  # declare list to hold test case results
        + f"{code}\n"  # inline submitted code
        + f"{testcases_str}\n"  # run test cases in try - except blocks
        + f"print(json.dumps({execution_results_list_identifier}))"  # print out the result list
    )

По сути, это создает строку с некоторыми импортами, затем вводит пользовательский код, затем добавляет серию блоков try - except, по одному для каждого тестового случая (представьте, что тестовый случай - это некий assert, который вызовет исключение, если код не сработает), в котором dict, представляющий детали выполнения теста, выталкивается в список, который в конечном итоге выводится в stdout и собирается процессом, в котором работает Django.

Это нормально для большинства случаев, но я хотел бы дать авторам больше гибкости в том, как они хотят тестировать свои программы.

Вместо того, чтобы жестко кодировать такую строку, я бы хотел, чтобы администратор мог указать шаблон для объединения пользовательского кода и тестовых примеров. Для программы на C это могло бы выглядеть так (это не язык шаблонов Django, это просто чтобы дать представление):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>

{{ USER_CODE }}

int main() {
{% for TEST in TESTCASES %}
   {
    {{ TEST.testcode }};
   }
{% endfor %}
    return 0;
}
<

Моя идея состоит в том, чтобы использовать определяемый администратором шаблон Django для конечного рендеринга в обычную строку, а не в HTML-страницу, как это обычно делается. Некоторые проблемы связаны с экранированием, правильным (де)отступом внедренного кода и простотой использования для тех, кому нужно создавать такие шаблоны.

Вернуться на верх