Как приводить значения параметров на основе их аннотаций в функциях python?

Рассмотрите возможность создания рабочего, который выполняет задачи из очереди задач. Я пытаюсь построить веб-интерфейс на django, чтобы запускать эти задачи вручную.

Пока что для некоторых встроенных типов данных я поступаю примерно так:

# tasks.py

@app.task
def add(a: int, b: int) -> int:
    return a+b
# views.py

TYPE_TO_FIELD_MAPPING = {
    str: forms.CharField,
    int: forms.IntegerField,
    float: forms.FloatField,
    datetime: forms.DateTimeField,
    # ...
}

class TaskTriggerView(View):

    def get(self, request):
        tasks = {}
        for task in app.tasks:
            tasks[task.name] = self.make_task_parameter_form(task)()
        return render(request, 'template.html', context={'tasks': tasks}
    
    def make_task_parameter_form(self, task):
        # every task has a signature property which
        # is an inspect.Signature object.
        task_signature: inspect.Signature = task.signature
        
        # Initialize a django form with fields made out of
        # task's function signature, where the form field
        # is based on it's annotation if annotation is in
        # `TYPE_TO_FIELD_MAPPING` else forms.CharField.
        # initial value comes from parameter's default value
        # if it is not parameter.empty.
        parameter_form = type(
                'ParameterForm', (forms.Form,),
                {param_name: TYPE_TO_FIELD_MAPPING.get(param.annotation, str)(
                    initial=None if param.default is param.empty else param.default
                )
                 for param_name, param in signature.parameters.items()})
        return parameter_form

    def post(self, request):
        task_name = request.POST.get('task_name')
        task = app.get_task_by_name(task_name)
        form_class = self.make_task_parameter_form(task)
        form = form_class(request.POST)
        if form.is_valid()
            # this sends the task to the queue
            task.send(**form.cleaned_data)
            return JsonResponse({'success': True})
        else:
            return JsonResponse({'success': False, 'errors': form.errors})

Мой вопрос заключается в том, как мне следует деконструировать более сложную аннотацию, например: List[str] из примера ниже?

@app.task
def concat_lists_of_names(a: List[str], b: List[str]):
    return a+b

В идеале я хотел бы иметь возможность различать parameter_type = list, component_type = str. А затем сопоставить его с пользовательским ListField(component_type=component_type), который будет проверять и приводить каждый компонент списка.

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