import copy from drf_spectacular.utils import OpenApiResponse from rest_framework import serializers def _build_schema_field(schema, *, many=False, required=True, allow_null=False): if schema is None: return serializers.JSONField(required=required, allow_null=allow_null) if isinstance(schema, serializers.Field): field = copy.deepcopy(schema) field.required = required if hasattr(field, "allow_null"): field.allow_null = allow_null return field if isinstance(schema, serializers.BaseSerializer): serializer = copy.deepcopy(schema) serializer.required = required serializer.allow_null = allow_null return serializer if isinstance(schema, type) and issubclass(schema, serializers.BaseSerializer): return schema(many=many, required=required, allow_null=allow_null) raise TypeError(f"Unsupported schema type: {type(schema)!r}") def build_message_response_serializer(name): return type( name, (serializers.Serializer,), { "__module__": __name__, "code": serializers.IntegerField(), "msg": serializers.CharField(), }, ) def build_envelope_serializer( name, data_schema=None, *, many=False, data_required=True, allow_null=False, ): return type( name, (serializers.Serializer,), { "__module__": __name__, "code": serializers.IntegerField(), "msg": serializers.CharField(), "data": _build_schema_field( data_schema, many=many, required=data_required, allow_null=allow_null, ), }, ) def build_task_queue_data_serializer(name, extra_fields=None): fields = { "__module__": __name__, "task_id": serializers.UUIDField(), "status_url": serializers.CharField(), } if extra_fields: fields.update(extra_fields) return type(name, (serializers.Serializer,), fields) def build_task_status_data_serializer(name, result_schema=None): result_field = ( _build_schema_field(result_schema, required=False, allow_null=True) if result_schema is not None else serializers.JSONField(required=False) ) return type( name, (serializers.Serializer,), { "__module__": __name__, "task_id": serializers.UUIDField(), "status": serializers.CharField(), "message": serializers.CharField(required=False), "progress": serializers.DictField( child=serializers.JSONField(), required=False, ), "result": result_field, "error": serializers.CharField(required=False), }, ) def build_response(serializer, description): return OpenApiResponse(response=serializer, description=description)