#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.web module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
from django.core.files import File
from rest_framework import exceptions as drf_exceptions
from rest_framework import parsers
from rest_framework import renderers
from rest_framework import response
from rest_framework import views
from ..code.api import DiffView
from ..code.api import RetrieveUpdateDestroyCodeView
from ..code.api import ShareCodeView
from ..code.serializers import CodeDiffSerializer
from ..common import permissions as beat_permissions
from ..common.api import CheckContributionNameView
from ..common.api import ListContributionView
from ..common.api import ListCreateContributionView
from .models import Algorithm
from .serializers import AlgorithmCreationSerializer
from .serializers import AlgorithmModSerializer
from .serializers import AlgorithmSerializer
from .serializers import FullAlgorithmSerializer
# ----------------------------------------------------------
[docs]class CheckAlgorithmNameView(CheckContributionNameView):
"""
This view sanitizes an algorithm name and
checks whether it is already used.
"""
model = Algorithm
# ----------------------------------------------------------
[docs]class ShareAlgorithmView(ShareCodeView):
"""
This view allows to share an algorithm with
other users and/or teams
"""
model = Algorithm
# ----------------------------------------------------------
[docs]class ListAlgorithmsView(ListContributionView):
"""
List all available algorithms
"""
model = Algorithm
serializer_class = AlgorithmSerializer
# ----------------------------------------------------------
[docs]class ListCreateAlgorithmsView(ListCreateContributionView):
"""
Read/Write end point that list the algorithms available
from a given author and allows the creation of new algorithms
"""
model = Algorithm
serializer_class = AlgorithmSerializer
writing_serializer_class = AlgorithmCreationSerializer
namespace = "api_algorithms"
# ----------------------------------------------------------
[docs]class RetrieveUpdateDestroyAlgorithmsView(RetrieveUpdateDestroyCodeView):
"""
Read/Write/Delete endpoint for a given algorithm
"""
model = Algorithm
serializer_class = FullAlgorithmSerializer
writing_serializer_class = AlgorithmModSerializer
# ----------------------------------------------------------
[docs]class DiffAlgorithmView(DiffView):
"""
This view shows the differences between two algorithms
"""
model = Algorithm
serializer_class = CodeDiffSerializer
# ----------------------------------------------------------
[docs]class BinaryRenderer(renderers.BaseRenderer):
media_type = "application/octet-stream"
charset = None
render_style = "binary"
[docs] def render(self, data, media_type=None, renderer_context=None):
return data
[docs]class FileHandlingView(views.APIView):
"""
This view handles the upload of binary files for non interpreted languages like
c++
"""
model = Algorithm
parser_classes = [parsers.MultiPartParser, parsers.FormParser]
renderer_classes = [BinaryRenderer]
permission_classes = [beat_permissions.IsAuthorOrReadOnly]
[docs] def get_object(self):
version = self.kwargs["version"]
author_name = self.kwargs["author_name"]
object_name = self.kwargs["object_name"]
user = self.request.user
try:
obj = self.model.objects.for_user(user, True).get(
author__username__iexact=author_name,
name__iexact=object_name,
version=version,
)
except self.model.DoesNotExist:
raise drf_exceptions.NotFound()
(has_access, _, _) = obj.accessibility_for(user, without_usable=True)
if not has_access:
raise drf_exceptions.NotFound()
if not obj.is_binary():
raise drf_exceptions.PermissionDenied(
"{} is not a binary algorithm".format(obj.fullname())
)
return obj
[docs] def get(self, request, author_name, object_name, version):
algorithm = self.get_object()
answer = response.Response(data=algorithm.source_code_file)
answer["Content-Disposition"] = "attachment; filename={}.so".format(
algorithm.version
)
return answer
[docs] def post(self, request, author_name, object_name, version):
algorithm = self.get_object()
if "binary" not in request.data:
raise drf_exceptions.ValidationError("Missing 'binary' field")
file_obj = request.data["binary"]
if not isinstance(file_obj, File):
raise drf_exceptions.ParseError("Invalid 'binary' content")
algorithm.source_code = file_obj.read()
algorithm.save()
return response.Response(status=204)