#!/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 ..common.api import ListContributionView
from .models import Plotter, PlotterParameter, DefaultPlotter
from .serializers import PlotterSerializer, PlotterParameterSerializer, DefaultPlotterSerializer
from .serializers import PlotterAllSerializer, PlotterCreationSerializer, FullPlotterSerializer
from .serializers import PlotterParameterAllSerializer, PlotterParameterCreationSerializer, FullPlotterParameterSerializer
from django.db.models import Q
from ..code.api import ShareCodeView, RetrieveUpdateDestroyCodeView
from ..code.serializers import CodeDiffSerializer
from ..code.api import DiffView
from ..common.api import (CheckContributionNameView, ShareView,
ListContributionView, ListCreateContributionView, RetrieveUpdateDestroyContributionView)
from ..common.utils import validate_restructuredtext, ensure_html
from ..common.responses import BadRequestResponse
from rest_framework import generics
from rest_framework import views
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from django.utils import six
from django.core.exceptions import ValidationError
import json
[docs]class ListPlotterView(ListContributionView):
"""
List all available plotters
"""
model = Plotter
serializer_class = PlotterSerializer
[docs]class ListPlotterParameterView(ListContributionView):
"""
List all available plotters parameters
"""
model = PlotterParameter
serializer_class = PlotterParameterSerializer
[docs] def get_queryset(self):
username = self.kwargs.get('author_name')
name = self.kwargs.get('dataformat_name')
version = self.kwargs.get('version')
if username and name and version:
return self.model.objects.filter(
dataformat__author__username = username,
dataformat__name = name,
dataformat__version = version)
else:
author_name = 'plot' if self.request.user.is_anonymous() else self.request.user.username
#return self.model.objects.all()
#from author and public and get latest version only
objects = self.model.objects.from_author_and_public(self.request.user, author_name).order_by('-version')
filtered_list = []
filtered_list_id = []
for the_item in objects:
check = False
for filtered_item in filtered_list:
if the_item.author == filtered_item.author and the_item.name == filtered_item.name:
check = True
if check == False:
filtered_list.append(the_item)
filtered_list_id.append(the_item.id)
objects = self.model.objects.from_author_and_public(self.request.user, author_name).order_by('-version').filter(id__in=filtered_list_id)
return objects
[docs]class ListDefaultPlotterView(generics.ListAPIView):
"""
List all available plotters
"""
model = DefaultPlotter
serializer_class = DefaultPlotterSerializer
[docs] def get_queryset(self):
return self.model.objects.all()
#----------------------------------------------------------
[docs]class CheckPlotterNameView(CheckContributionNameView):
"""
This view sanitizes a Plotter name and
checks whether it is already used.
"""
model = Plotter
#----------------------------------------------------------
class SharePlotterParameterView(ShareCodeView):
"""
This view allows to share a plotterparameter with
other users and/or teams
"""
model = PlotterParameter
#----------------------------------------------------------
[docs]class ListCreatePlottersView(ListCreateContributionView):
"""
Read/Write end point that list the plotters available
from a given author and allows the creation of new plotters
"""
model = Plotter
serializer_class = PlotterAllSerializer
writing_serializer_class = PlotterCreationSerializer
namespace = 'api_plotters'
#----------------------------------------------------------
[docs]class RetrieveUpdateDestroyPlottersView(RetrieveUpdateDestroyCodeView):
"""
Read/Write/Delete endpoint for a given plotter
"""
model = Plotter
serializer_class = FullPlotterSerializer
[docs] def get_queryset(self):
plotter_author = self.kwargs.get('author_name')
plotter_name = self.kwargs.get('object_name')
plotter_version = self.kwargs.get('version')
#plotter = get_object_or_404(Plotter, author__username=plotter_author, name=plotter_name, version=plotter_version)
plotter = Plotter.objects.filter(author__username=plotter_author, name=plotter_name, version=plotter_version)
self.check_object_permissions(self.request, plotter)
return plotter
#def do_update(self, request, author_name, object_name, version=None):
# modified, algorithm = super(RetrieveUpdateDestroyPlottersView, self).do_update(request, author_name, object_name, version)
# if modified:
# # Delete existing experiments using the algorithm (code changed)
# experiments = list(set(map(lambda x: x.experiment,
# algorithm.blocks.iterator())))
# for experiment in experiments: experiment.delete()
# return modified, algorithm
##----------------------------------------------------------
#
#
#class DiffPlotterView(DiffView):
# """
# This view shows the differences between two algorithms
# """
# model = Algorithm
# serializer_class = CodeDiffSerializer
#----------------------------------------------------------
[docs]class CheckPlotterParameterNameView(CheckContributionNameView):
"""
This view sanitizes a PlotterParameter name and
checks whether it is already used.
"""
model = PlotterParameter
#----------------------------------------------------------
[docs]class SharePlotterParameterView(ShareView):
"""
This view allows to share a PlotterParameter with
other users and/or teams
"""
model = PlotterParameter
#----------------------------------------------------------
[docs]class ListPlotterParametersView(ListCreateContributionView):
"""
List all available PlotterParameters
"""
model = PlotterParameter
serializer_class = FullPlotterParameterSerializer
writing_serializer_class = PlotterParameterCreationSerializer
namespace = 'api_plotters'
#def get_queryset(self):
# # get all plotterparameter accessible for user (private+public)
# queryset = PlotterParameter.objects.for_user(self.request.user, True)
# return queryset
#----------------------------------------------------------
#class ListCreatePlotterParametersView(ListCreateContributionView):
# """
# Read/Write end point that list the PlotterParameters available
# from a given author and allows the creation of new PlotterParameters
# """
# model = PlotterParameter
# serializer_class = FullPlotterParameterSerializer
# namespace = 'api_plotterparameters'
#----------------------------------------------------------
[docs]class RetrieveUpdateDestroyPlotterParametersView(RetrieveUpdateDestroyContributionView):
"""
Read/Write/Delete endpoint for a given PlotterParameter
"""
model = PlotterParameter
serializer_class = FullPlotterParameterSerializer
[docs] def put(self, request, author_name, object_name, version=None):
if version is None:
return BadRequestResponse('A version number must be provided')
try:
data = request.data
except ParseError as e:
raise serializers.ValidationError({'data': str(e)})
else:
if not data:
raise serializers.ValidationError({'data': 'Empty'})
if 'short_description' in data:
if not(isinstance(data['short_description'], six.string_types)):
raise serializers.ValidationError({'short_description', 'Invalid short_description data'})
short_description = data['short_description']
else:
short_description = None
if 'description' in data:
if not(isinstance(data['description'], six.string_types)):
raise serializers.ValidationError({'description': 'Invalid description data'})
description = data['description']
try:
validate_restructuredtext(description)
except ValidationError as errors:
raise serializers.ValidationError({'description': [error for error in errors]})
else:
description = None
if 'strict' in data:
strict = data['strict']
else:
strict = True
plotter = None
if 'plotter' in data:
try:
if isinstance(data['plotter'], int):
plotter = Plotter.objects.get(id=data['plotter'])
else:
return BadRequestResponse('A valid plotter id number must be provided')
except:
return BadRequestResponse('A valid plotter id number must be provided')
if (short_description is not None) and (len(short_description) > self.model._meta.get_field('short_description').max_length):
raise serializers.ValidationError({'short_description': 'Short description too long'})
customdata = None
if 'customdata' in data:
customdata = json.dumps(data['customdata'])
# Process the query string
if 'fields' in request.GET:
fields_to_return = request.GET['fields'].split(',')
else:
# Available fields (not returned by default):
# - html_description
fields_to_return = ['errors']
# Retrieve the plotterparameter
dbplotterparameter = get_object_or_404(PlotterParameter,
author__username__iexact=author_name,
name__iexact=object_name,
version=version)
# Check that the object can still be modified (if applicable, the
# documentation can always be modified)
if not dbplotterparameter.modifiable():
raise PermissionDenied("The {} isn't modifiable anymore (either shared with someone else, or needed by an attestation)".format(dbplotterparameter.model_name()))
errors = None
# Modification of the short_description
if (short_description is not None):
dbplotterparameter.short_description = short_description
# Modification of the description
if description is not None:
dbplotterparameter.description = description
# Modification of the plotter
if plotter is not None:
dbplotterparameter.plotter = plotter
# Modification of the parameters
if customdata is not None:
dbplotterparameter.data = customdata
# Save the plotterparameter model
try:
dbplotterparameter.save()
except Exception as e:
return BadRequestResponse(str(e))
# Nothing to return?
if len(fields_to_return) == 0:
return Response(status=204)
result = {}
# Retrieve the errors (if necessary)
if 'errors' in fields_to_return:
if errors:
result['errors'] = errors
else:
result['errors'] = ''
# Retrieve the description in HTML format (if necessary)
if 'html_description' in fields_to_return:
description = dbplotterparameter.description
if len(description) > 0:
result['html_description'] = ensure_html(description)
else:
result['html_description'] = ''
return Response(result)