Skip to content
Snippets Groups Projects
Commit e7d4c494 authored by Samuel GAIST's avatar Samuel GAIST
Browse files

[attestations][all] Pre-commit cleanup

parent befdb539
No related branches found
No related tags found
2 merge requests!346Cleanup attestations,!342Django 3 migration
Pipeline #42556 passed
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -25,23 +25,32 @@
# #
###############################################################################
from .models import Attestation as AttestationModel
from django.contrib import admin
from .models import Attestation as AttestationModel
class Attestation(admin.ModelAdmin):
list_display = ('id', 'number', 'experiment', 'locked', 'creation_date', 'expiration_date', 'publication_date',)
search_fields = [
'number',
'experiment__name',
'experiment__author__username',
'experiment__toolchain__author__username',
'experiment__toolchain__name',
'experiment__toolchain__version',
list_display = (
"id",
"number",
"experiment",
"locked",
"creation_date",
"expiration_date",
"publication_date",
)
search_fields = [
"number",
"experiment__name",
"experiment__author__username",
"experiment__toolchain__author__username",
"experiment__toolchain__name",
"experiment__toolchain__version",
]
list_filter = ('locked', )
list_display_links = ('id', 'number')
list_filter = ("locked",)
list_display_links = ("id", "number")
admin.site.register(AttestationModel, Attestation)
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -27,83 +27,73 @@
from django.conf import settings
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework import generics
from rest_framework import permissions
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from datetime import datetime
from .models import Attestation
from .serializers import AttestationSerializer
from .exceptions import AlreadyUnlockedError
from ..experiments.models import Experiment
from ..common.models import Shareable
from ..common.exceptions import ShareError
from ..common.responses import BadRequestResponse, ForbiddenResponse
import beat.core.experiment
import beat.core.toolchain
import simplejson as json
from ..common.exceptions import ShareError
from ..common.responses import BadRequestResponse
from ..common.responses import ForbiddenResponse
from ..experiments.models import Experiment
from .exceptions import AlreadyUnlockedError
from .models import Attestation
from .serializers import AttestationSerializer
#----------------------------------------------------------
# ----------------------------------------------------------
class CreateAttestationView(APIView):
"""
Create a new attestation
"""
permission_classes = [permissions.IsAuthenticated]
def post(self, request):
data = request.data
if 'experiment' not in data:
return BadRequestResponse('Missing field: experiment')
if "experiment" not in data:
return BadRequestResponse("Missing field: experiment")
if not(isinstance(data['experiment'], str)):
return BadRequestResponse('Invalid field type: "experiment" must be a string')
if not (isinstance(data["experiment"], str)):
return BadRequestResponse(
'Invalid field type: "experiment" must be a string'
)
declaration_id = beat.core.experiment.Storage(settings.PREFIX,
data['experiment'])
declaration_id = beat.core.experiment.Storage(
settings.PREFIX, data["experiment"]
)
# Check that the user is the author of the experiment
if declaration_id.username != request.user.username:
return ForbiddenResponse()
# Retrieve the experiment
try:
toolchain_id = beat.core.toolchain.Storage(settings.PREFIX,
declaration_id.toolchain)
experiment = Experiment.objects.get(
author__username=declaration_id.username,
toolchain__author__username=toolchain_id.username,
toolchain__name=toolchain_id.name,
toolchain__version=toolchain_id.version,
name=declaration_id.name
)
except:
return Response(status=404)
toolchain_id = beat.core.toolchain.Storage(
settings.PREFIX, declaration_id.toolchain
)
experiment = get_object_or_404(
Experiment,
author__username=declaration_id.username,
toolchain__author__username=toolchain_id.username,
toolchain__name=toolchain_id.name,
toolchain__version=toolchain_id.version,
name=declaration_id.name,
)
# Check that an attestation doesn't already exists for that experiment
if experiment.has_attestation():
return BadRequestResponse('This experiment already has an attestation')
return BadRequestResponse("This experiment already has an attestation")
# Check that the experiment is done
if experiment.end_date is None:
return BadRequestResponse("This experiment isn't done yet")
# Retrieve and process the list of algorithms referenced by the declaration, and
# their referenced data formats
needed_formats = []
......@@ -115,10 +105,10 @@ class CreateAttestationView(APIView):
needed_formats = list(set(needed_formats))
needed_algorithms = list(set(needed_algorithms))
# Process the list of referenced dataformats
other_needed_formats = filter(lambda x: x.author != experiment.author, needed_formats)
other_needed_formats = filter(
lambda x: x.author != experiment.author, needed_formats
)
# Ensure that all needed dataformats from other users have the necessary sharing
# preferences
......@@ -129,11 +119,10 @@ class CreateAttestationView(APIView):
if len(errors) > 0:
return Response(errors, status=400)
# Process the list of referenced algorithms
own_needed_algorithms = filter(lambda x: x.author == experiment.author, needed_algorithms)
other_needed_algorithms = filter(lambda x: x.author != experiment.author, needed_algorithms)
other_needed_algorithms = filter(
lambda x: x.author != experiment.author, needed_algorithms
)
# Ensure that all needed algorithms from other users have the necessary sharing
# preferences
......@@ -157,37 +146,37 @@ class CreateAttestationView(APIView):
# Send the result
result = {
'number': attestation.number,
"number": attestation.number,
}
response = Response(result, status=201)
return response
#----------------------------------------------------------
# ----------------------------------------------------------
class UnlockAttestationView(APIView):
"""
Unlock a "locked" attestation
"""
permission_classes = [permissions.IsAuthenticated]
def post(self, request, number):
data = request.data
if 'visible_algorithms' in data:
if not(isinstance(data['visible_algorithms'], list)):
return BadRequestResponse('Invalid visible_algorithms data')
if "visible_algorithms" in data:
if not (isinstance(data["visible_algorithms"], list)):
return BadRequestResponse("Invalid visible_algorithms data")
if len(data['visible_algorithms']) > 0:
visible_algorithms_names = data['visible_algorithms']
if len(data["visible_algorithms"]) > 0:
visible_algorithms_names = data["visible_algorithms"]
else:
visible_algorithms_names = []
else:
visible_algorithms_names = []
# Retrieve the attestation
attestation = get_object_or_404(Attestation, number=number)
......@@ -199,26 +188,31 @@ class UnlockAttestationView(APIView):
try:
attestation.unlock(visible_algorithms_names=visible_algorithms_names)
except AlreadyUnlockedError:
return BadRequestResponse('This attestation is already unlocked')
return BadRequestResponse("This attestation is already unlocked")
except ShareError as e:
return Response(e.errors, status=400)
return Response(status=204)
#----------------------------------------------------------
# ----------------------------------------------------------
class ListUserAttestationView(generics.ListAPIView):
"""
List all attestations from a given user
"""
permission_classes = [permissions.AllowAny]
serializer_class = AttestationSerializer
def get(self, request, username):
# Retrieve all the attestations of the specified user
attestations = Attestation.objects.select_related().filter(experiment__author__username=username).order_by('-creation_date')
attestations = (
Attestation.objects.select_related()
.filter(experiment__author__username=username)
.order_by("-creation_date")
)
if username != request.user.username:
attestations = attestations.exclude(locked=True)
......@@ -227,13 +221,14 @@ class ListUserAttestationView(generics.ListAPIView):
return Response(serializer.data)
#----------------------------------------------------------
# ----------------------------------------------------------
class DeleteAttestationView(APIView):
"""
Delete given attestation if locked
"""
permission_classes = [permissions.IsAuthenticated]
def delete(self, request, number):
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -25,15 +25,19 @@
# #
###############################################################################
from ..common.apps import CommonAppConfig
from django.utils.translation import ugettext_lazy as _
from ..common.apps import CommonAppConfig
class AttestationsConfig(CommonAppConfig):
name = 'beat.web.attestations'
verbose_name = _('Attestations')
name = "beat.web.attestations"
verbose_name = _("Attestations")
def ready(self):
super(AttestationsConfig, self).ready()
from .signals.handlers import on_unlocked
from actstream import registry
registry.register(self.get_model('Attestation'))
from .signals.handlers import on_unlocked # noqa: F401
registry.register(self.get_model("Attestation"))
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -28,8 +28,8 @@
"""
Attestation specific exceptions
"""
from ..common.exceptions import BeatWebError
class AlreadyUnlockedError(BeatWebError):
pass
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -25,44 +25,46 @@
# #
###############################################################################
from django.db import models
import random
from datetime import datetime
from datetime import timedelta
from django.conf import settings
from django.db import models
from django.urls import reverse
from ..experiments.models import Experiment
from ..toolchains.models import Toolchain
from ..algorithms.models import Algorithm
from ..dataformats.models import DataFormat
from .signals import unlocked
from ..experiments.models import Experiment
from ..toolchains.models import Toolchain
from .exceptions import AlreadyUnlockedError
from .signals import unlocked
import random
from datetime import datetime, timedelta
class AttestationManager(models.Manager):
def get_by_natural_key(self, number):
return self.get(number=number)
def create_attestation(self, experiment):
# Generate a unique attestation number
used_numbers = [attestation.number for attestation in self.model.objects.all()]
used_numbers = self.model.objects.values_list("number", flat=True)
number = 0
while (number == 0) or number in used_numbers:
number = random.randint(100000, 2**31)
number = random.randint(100000, 2 ** 31) # nosec
creation_date = datetime.now()
expiration_date = creation_date + timedelta(days=settings.EXPIRATION_DELTA)
attestation = self.model(number=number,
experiment=experiment,
toolchain=experiment.toolchain,
locked=True,
creation_date=creation_date,
expiration_date=expiration_date,
publication_date=None)
attestation = self.model(
number=number,
experiment=experiment,
toolchain=experiment.toolchain,
locked=True,
creation_date=creation_date,
expiration_date=expiration_date,
publication_date=None,
)
attestation.save()
return attestation
......@@ -76,67 +78,78 @@ class AttestationManager(models.Manager):
class Attestation(models.Model):
number = models.IntegerField()
experiment = models.OneToOneField(Experiment, related_name='attestation', on_delete=models.CASCADE)
locked = models.BooleanField(default=True)
creation_date = models.DateTimeField()
number = models.IntegerField()
experiment = models.OneToOneField(
Experiment, related_name="attestation", on_delete=models.CASCADE
)
locked = models.BooleanField(default=True)
creation_date = models.DateTimeField()
publication_date = models.DateTimeField(null=True, blank=True)
expiration_date = models.DateTimeField(null=True, blank=True)
toolchain = models.ForeignKey(Toolchain, related_name='attestations',
null=True, blank=True, on_delete=models.CASCADE)
dataformats = models.ManyToManyField(DataFormat, related_name='attestations',
blank=True)
algorithms = models.ManyToManyField(Algorithm, related_name='attestations',
blank=True)
toolchain = models.ForeignKey(
Toolchain,
related_name="attestations",
null=True,
blank=True,
on_delete=models.CASCADE,
)
dataformats = models.ManyToManyField(
DataFormat, related_name="attestations", blank=True
)
algorithms = models.ManyToManyField(
Algorithm, related_name="attestations", blank=True
)
objects = AttestationManager()
def __str__(self):
return "Attestation #%d, for experiment %s" % (self.number, self.experiment.fullname())
return "Attestation #%d, for experiment %s" % (
self.number,
self.experiment.fullname(),
)
def natural_key(self):
return (self.number,)
def get_absolute_url(self):
return reverse(
'attestations:view',
args=(
self.number,
),
)
return reverse("attestations:view", args=(self.number,),)
def modifiable(self):
return not(self.locked) and super(Attestation, self).modifiable()
return not (self.locked) and super(Attestation, self).modifiable()
def deletable(self):
return not(self.locked) and super(Attestation, self).deletable()
return not (self.locked) and super(Attestation, self).deletable()
def list_of_referenced_formats(self):
s = '['
s = "["
for dataformat in self.dataformats.all():
s += "'%s'," % dataformat.fullname()
if s[-1] == ',':
if s[-1] == ",":
s = s[:-1]
return s + ']'
return s + "]"
def share(self, visible_algorithms_names):
# Build algorithms sharing information
own_needed_algorithms = self.experiment.referenced_algorithms.filter(author=self.experiment.author)
own_needed_algorithms = self.experiment.referenced_algorithms.filter(
author=self.experiment.author
)
algorithms_infos = {}
visible_algorithms = filter(lambda x: x.fullname() in visible_algorithms_names,
own_needed_algorithms)
visible_algorithms = filter(
lambda x: x.fullname() in visible_algorithms_names, own_needed_algorithms
)
for visible_algorithm in visible_algorithms:
algorithms_infos[visible_algorithm.fullname()] = {'opensource': False}
algorithms_infos[visible_algorithm.fullname()] = {"opensource": False}
public_algorithms = filter(lambda x: x.fullname() not in visible_algorithms_names,
own_needed_algorithms)
public_algorithms = filter(
lambda x: x.fullname() not in visible_algorithms_names,
own_needed_algorithms,
)
for public_algorithm in public_algorithms:
algorithms_infos[public_algorithm.fullname()] = {'opensource': True}
algorithms_infos[public_algorithm.fullname()] = {"opensource": True}
# Share the experiment
self.experiment.share(algorithms_infos=algorithms_infos)
......@@ -146,7 +159,7 @@ class Attestation(models.Model):
# Share the experiment
self.share(visible_algorithms_names=visible_algorithms_names)
# Unlock the attestation
self.locked = False
self.locked = False
self.publication_date = datetime.now()
self.save()
unlocked.send(self)
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -38,7 +38,14 @@ class AttestationSerializer(serializers.ModelSerializer):
class Meta:
model = Attestation
fields = ['number', 'experiment', 'locked',
'creation_date', 'expiration_date', 'publication_date',
'toolchain',
'nb_dataformats', 'nb_algorithms']
fields = [
"number",
"experiment",
"locked",
"creation_date",
"expiration_date",
"publication_date",
"toolchain",
"nb_dataformats",
"nb_algorithms",
]
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
......@@ -27,27 +27,26 @@
import io
import os
import simplejson as json
import shutil
from datetime import datetime, timedelta
from datetime import datetime
from datetime import timedelta
from django.contrib.auth.models import User
import simplejson as json
from django.conf import settings
from django.urls import reverse
from django.contrib.auth.models import User
from django.core.management import call_command
from django.urls import reverse
from ..experiments.models import Experiment
from ..algorithms.models import Algorithm
from ..backend.models import Environment
from ..backend.models import Queue
from ..common.models import Shareable
from ..backend.models import Environment, Queue
from ..dataformats.models import DataFormat
from ..toolchains.models import Toolchain
from ..databases.models import Database
from ..common.testutils import BaseTestCase
from ..common.testutils import tearDownModule # noqa test runner will call it
from ..databases.models import Database
from ..dataformats.models import DataFormat
from ..experiments.models import Experiment
from ..toolchains.models import Toolchain
from .models import Attestation
TEST_PWD = "1234"
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
#!/usr/bin/env python
# encoding: utf-8
###############################################################################
......@@ -30,10 +28,10 @@
# Mon 14 Sep 13:15:34 CEST 2015
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.contrib.auth.models import User
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from .models import Attestation
......@@ -45,54 +43,53 @@ def view(request, number):
(has_access, _) = attestation.experiment.accessibility_for(request.user)
# Render the page
return render(request,
'attestations/view.html',
dict(
attestation=attestation,
has_access=has_access,
owner=(attestation.experiment.author == request.user)
))
return render(
request,
"attestations/view.html",
dict(
attestation=attestation,
has_access=has_access,
owner=(attestation.experiment.author == request.user),
),
)
def ls(request, author_name):
'''List all accessible attestations to the request user'''
"""List all accessible attestations to the request user"""
if not author_name: return public_ls(request)
if not author_name:
return public_ls(request)
# check that the user exists on the system
author = get_object_or_404(User, username=author_name)
if request.user == author:
# list all of the users attestations
objects = Attestation.objects.filter(Q(experiment__author=author) | \
Q(locked=False))
objects = Attestation.objects.filter(
Q(experiment__author=author) | Q(locked=False)
)
else:
# list all unlocked (public) attestations from a given user
objects = Attestation.objects.filter(experiment__author=author,
locked=False)
objects = Attestation.objects.filter(experiment__author=author, locked=False)
objects = objects.order_by('-locked', 'expiration_date')
objects = objects.order_by("-locked", "expiration_date")
return render(request,
'attestations/list.html',
dict(
objects=objects,
author=author,
owner=(request.user == author)
))
return render(
request,
"attestations/list.html",
dict(objects=objects, author=author, owner=(request.user == author)),
)
def public_ls(request):
'''List all accessible attestations to any user'''
"""List all accessible attestations to any user"""
# orders so that recent objects are displayed first
objects = Attestation.objects.filter(locked=False).order_by('-publication_date')
return render(request,
'attestations/list.html',
dict(
objects=objects,
author=request.user, # anonymous
owner=False,
))
objects = Attestation.objects.filter(locked=False).order_by("-publication_date")
return render(
request,
"attestations/list.html",
dict(objects=objects, author=request.user, owner=False,), # anonymous
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment