Commit f02be244 authored by Samuel GAIST's avatar Samuel GAIST Committed by Flavio TARSETTI
Browse files

[search][all] Pre-commit cleanup

parent 5966d8bd
Pipeline #42666 passed with stage
in 15 minutes and 30 seconds
......@@ -25,18 +25,18 @@
# #
###############################################################################
from django.contrib import admin
from django import forms
from django.contrib import admin
from ..common.texts import Messages
from .models import Search, Leaderboard, Rank
from ..ui.forms import CodeMirrorRSTCharField
from ..ui.forms import CodeMirrorJSONCharField
from ..ui.forms import CodeMirrorRSTCharField
from ..ui.forms import NameField
from .models import Leaderboard
from .models import Rank
from .models import Search
#----------------------------------------------------------
# ----------------------------------------------------------
def rehash_search(modeladmin, request, queryset):
......@@ -44,64 +44,57 @@ def rehash_search(modeladmin, request, queryset):
for q in queryset:
q.save()
rehash_search.short_description = 'Rehash selected search'
rehash_search.short_description = "Rehash selected search"
#----------------------------------------------------------
# ----------------------------------------------------------
class SearchModelForm(forms.ModelForm):
name = NameField(
widget=forms.TextInput(attrs=dict(size=80)),
help_text=Messages['algo_name'],
widget=forms.TextInput(attrs=dict(size=80)), help_text=Messages["algo_name"],
)
description = CodeMirrorRSTCharField(
required=False,
help_text=Messages['description'],
required=False, help_text=Messages["description"],
)
filters = CodeMirrorJSONCharField(
readonly=False,
required=False,
help_text=Messages['json'],
readonly=False, required=False, help_text=Messages["json"],
)
settings = CodeMirrorJSONCharField(
readonly=False,
required=False,
help_text=Messages['json'],
readonly=False, required=False, help_text=Messages["json"],
)
class Meta:
model = Search
exclude = []
widgets = {
'short_description': forms.TextInput(
attrs=dict(size=100),
),
"short_description": forms.TextInput(attrs=dict(size=100),),
}
#----------------------------------------------------------
# ----------------------------------------------------------
class SearchAdmin(admin.ModelAdmin):
list_display = ('id', 'author', 'name')
search_fields = [
'author__username',
'name',
'short_description',
'description',
'filters',
'settings',
list_display = ("id", "author", "name")
search_fields = [
"author__username",
"name",
"short_description",
"description",
"filters",
"settings",
]
list_display_links = ('id', 'name')
list_display_links = ("id", "name")
list_filter = ('author', 'name', 'version')
readonly_fields = ('hash',)
list_filter = ("author", "name", "version")
readonly_fields = ("hash",)
actions = [
rehash_search,
......@@ -109,87 +102,98 @@ class SearchAdmin(admin.ModelAdmin):
form = SearchModelForm
filter_horizontal = [
'shared_with',
'shared_with_team'
]
filter_horizontal = ["shared_with", "shared_with_team"]
fieldsets = (
(None,
dict(
fields=('name', 'author',),
),
),
('Documentation',
dict(
classes=('collapse',),
fields=('short_description', 'description',),
),
),
('Versioning',
dict(
classes=('collapse',),
fields=('version', 'previous_version', 'fork_of'),
),
),
('Sharing',
dict(
classes=('collapse',),
fields=('sharing', 'shared_with', 'shared_with_team'),
),
),
('Definition',
dict(
fields=('hash', 'filters', 'settings'),
),
),
(None, dict(fields=("name", "author",),),),
(
"Documentation",
dict(classes=("collapse",), fields=("short_description", "description",),),
),
(
"Versioning",
dict(
classes=("collapse",),
fields=("version", "previous_version", "fork_of"),
),
),
(
"Sharing",
dict(
classes=("collapse",),
fields=("sharing", "shared_with", "shared_with_team"),
),
),
("Definition", dict(fields=("hash", "filters", "settings"),),),
)
admin.site.register(Search, SearchAdmin)
class RankInline(admin.TabularInline):
model = Rank
can_delete = False
extra = 0
max_num = 0
readonly_fields = ('id', 'algorithm', 'result', 'order', 'experiment')
ordering = ('algorithm', 'order',)
model = Rank
can_delete = False
extra = 0
max_num = 0
readonly_fields = ("id", "algorithm", "result", "order", "experiment")
ordering = (
"algorithm",
"order",
)
def number_of_experiments(obj):
return obj.experiments.count()
number_of_experiments.short_description = 'Experiments'
number_of_experiments.short_description = "Experiments"
def users_to_notify(obj):
return obj.notify.count()
users_to_notify.short_description = 'Subscribed'
users_to_notify.short_description = "Subscribed"
def search_sharing(obj):
return obj.search.get_sharing_display()
search_sharing.short_description = 'Sharing'
search_sharing.short_description = "Sharing"
class LeaderboardAdmin(admin.ModelAdmin):
list_display = ('id', 'search', 'created', 'updated', users_to_notify, number_of_experiments, search_sharing)
list_display = (
"id",
"search",
"created",
"updated",
users_to_notify,
number_of_experiments,
search_sharing,
)
search_fiels = [
'search__author__username',
'search__name',
'search_short_description',
'search_description',
'filters',
'settings',
"search__author__username",
"search__name",
"search_short_description",
"search_description",
"filters",
"settings",
]
list_display_links = ('id', 'search',)
list_display_links = (
"id",
"search",
)
inlines = [
RankInline,
]
filter_horizontal = [
'notify',
"notify",
]
admin.site.register(Leaderboard, LeaderboardAdmin)
......@@ -26,46 +26,40 @@
###############################################################################
import simplejson as json
from functools import reduce
import simplejson as json
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models import Q
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import permissions as drf_permissions
from rest_framework import generics
from rest_framework import permissions as drf_permissions
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from ..algorithms.models import Algorithm
from ..common import permissions as beat_permissions
from ..common.api import ShareView
from ..common.mixins import CommonContextMixin
from ..common.mixins import SerializerFieldsMixin
from ..common.models import Shareable
from ..common.responses import BadRequestResponse
from ..common.utils import ensure_html
from ..common.utils import py3_cmp
from ..databases.models import Database
from ..dataformats.models import DataFormat
from ..experiments.models import Experiment
from ..toolchains.models import Toolchain
from ..common.models import Shareable
from ..common.api import ShareView
from ..common.utils import ensure_html
from ..common.responses import BadRequestResponse
from ..common.mixins import CommonContextMixin, SerializerFieldsMixin
from ..common.utils import py3_cmp
from ..common import permissions as beat_permissions
from ..ui.templatetags.gravatar import gravatar_hash
from .utils import apply_filter
from .utils import FilterGenerator
from .utils import OR
from .models import Search
from .serializers import SearchResultSerializer, SearchSerializer, SearchWriteSerializer
from .serializers import SearchResultSerializer
from .serializers import SearchSerializer
from .serializers import SearchWriteSerializer
from .utils import OR
from .utils import FilterGenerator
from .utils import apply_filter
# ------------------------------------------------
......@@ -111,9 +105,9 @@ class SearchView(APIView):
filters = None
display_settings = None
if 'query' in data:
if not(isinstance(data['query'], str)) or (len(data['query']) == 0):
return BadRequestResponse('Invalid query data')
if "query" in data:
if not (isinstance(data["query"], str)) or (len(data["query"]) == 0):
return BadRequestResponse("Invalid query data")
query = data["query"]
else:
......
......@@ -25,14 +25,17 @@
# #
###############################################################################
from ..common.apps import CommonAppConfig
from django.utils.translation import ugettext_lazy as _
from ..common.apps import CommonAppConfig
class SearchConfig(CommonAppConfig):
name = 'beat.web.search'
verbose_name = _('Search')
name = "beat.web.search"
verbose_name = _("Search")
def ready(self):
super(SearchConfig, self).ready()
from actstream import registry
registry.register(self.get_model('Search'))
registry.register(self.get_model("Search"))
......@@ -27,5 +27,6 @@
from rest_framework import serializers
class DictListField(serializers.ListField):
child = serializers.DictField()
......@@ -25,41 +25,40 @@
# #
###############################################################################
import copy
import datetime
import operator
import simplejson as json
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
from beat.core.hash import hash
from ..common.texts import Messages
from ..common.models import Contribution
from ..experiments.models import Experiment, Result
from ..algorithms.models import Algorithm
import copy
import operator
import datetime
import simplejson as json
from ..common.models import Contribution
from ..common.texts import Messages
from ..experiments.models import Experiment
from ..experiments.models import Result
# date/time for the 1st january 1970, UTC
EPOCH = datetime.datetime.utcfromtimestamp(0)
class Search(Contribution):
class Meta:
verbose_name_plural = 'searches'
filters = models.TextField(default='', blank=True)
settings = models.TextField(default='', blank=True)
description = models.TextField(default='', blank=True, help_text=Messages['description'])
verbose_name_plural = "searches"
filters = models.TextField(default="", blank=True)
settings = models.TextField(default="", blank=True)
description = models.TextField(
default="", blank=True, help_text=Messages["description"]
)
def fullname(self):
return '{}/{}'.format(self.author.username, self.name)
return "{}/{}".format(self.author.username, self.name)
def save(self, *args, **kwargs):
# Compute the hash
......@@ -69,73 +68,61 @@ class Search(Contribution):
super(Search, self).save(*args, **kwargs)
# If there is a leaderboard, make sure to update it as well
if hasattr(self, 'leaderboard'):
self.leaderboard.save() #force update
if hasattr(self, "leaderboard"):
self.leaderboard.save() # force update
def get_absolute_url(self):
return reverse(
'search:view',
args=(
self.author.username,
self.name,
),
)
return reverse("search:view", args=(self.author.username, self.name,),)
def get_notify_url(self):
return reverse(
'search:notify',
args=(
self.author.username,
self.name,
),
)
return reverse("search:notify", args=(self.author.username, self.name,),)
def get_api_update_url(self):
'''Returns the endpoint to update this object'''
return reverse(
'api_search:save',
args=(self.author.username, self.name,),
)
"""Returns the endpoint to update this object"""
return reverse("api_search:save", args=(self.author.username, self.name,),)
def get_api_share_url(self):
'''Returns the endpoint to share this object'''
return reverse(
'api_search:share',
args=(self.author.username, self.name,),
)
"""Returns the endpoint to share this object"""
return reverse("api_search:share", args=(self.author.username, self.name,),)
def has_leaderboard(self):
return hasattr(self, 'leaderboard')
return hasattr(self, "leaderboard")
class LeaderboardManager(models.Manager):
def get_by_natural_key(self, username, name, version):
return self.get(search__author__username=username, search__name=name, search__version=version)
return self.get(
search__author__username=username,
search__name=name,
search__version=version,
)
class Leaderboard(models.Model):
'''Keeps track of experiments'''
"""Keeps track of experiments"""
search = models.OneToOneField(Search, related_name='leaderboard', on_delete=models.CASCADE)
search = models.OneToOneField(
Search, related_name="leaderboard", on_delete=models.CASCADE
)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
changed = models.DateTimeField(default=datetime.datetime.now)
notify = models.ManyToManyField(User, limit_choices_to={'is_active': True}, blank=True, help_text='If set, and the leader board changes, an e-mail notification will be sent to people on this list, every time it changes.')
notify = models.ManyToManyField(
User,
limit_choices_to={"is_active": True},
blank=True,
help_text="If set, and the leader board changes, an e-mail notification will be sent to people on this list, every time it changes.",
)
experiments = models.ManyToManyField(Experiment,
through='Rank',
related_name='leaderboards',
blank=True,
help_text='Experiments currently set on the leaderboard',
experiments = models.ManyToManyField(
Experiment,
through="Rank",
related_name="leaderboards",
blank=True,
help_text="Experiments currently set on the leaderboard",
)
objects = LeaderboardManager()
......@@ -145,25 +132,21 @@ class Leaderboard(models.Model):
def natural_key(self):
return (self.search.author.username, self.search.name, self.search.version)
natural_key.dependencies = ['search.search']
natural_key.dependencies = ["search.search"]
def get_absolute_url(self):
return reverse(
'search:view',
args=(
self.search.author.username,
self.search.name,
),
"search:view", args=(self.search.author.username, self.search.name,),
)
def current_experiments(self, time_delta=None):
'''Returns a list of experiments, sorted by criteria in settings
"""Returns a list of experiments, sorted by criteria in settings
If you specify a ``time_delta``, then we won't consider experiments
which are newer than ``now - time_delta``. ``time_delta`` should be set
as a ``datetime.timedelta`` object.
'''
"""
# reset experiments
from .views import search_experiments
......@@ -174,14 +157,16 @@ class Leaderboard(models.Model):
# creates multiple tables (per common analyzer), with experiments
# and existing table-able results (simple numbers)
sorted_experiments = []
for analyzer, blocks in results['common_analyzers']:
for analyzer, blocks in results["common_analyzers"]:
table = []
header = []
for block in blocks:
analyzer_output = Result.objects.filter(cache__in=block.outputs.all(), type__in=Result.SIMPLE_TYPE_NAMES).order_by('name')
analyzer_output = Result.objects.filter(
cache__in=block.outputs.all(), type__in=Result.SIMPLE_TYPE_NAMES
).order_by("name")
if not header: #first row, set order
if not header: # first row, set order
header = [k.name for k in analyzer_output]
table.append([block.experiment] + list(analyzer_output))
......@@ -192,16 +177,17 @@ class Leaderboard(models.Model):
ordering = json.loads(self.search.settings)
for entry in ordering:
if not entry['analyzers']: continue
if not entry["analyzers"]:
continue
# if an analyzer is set, apply ordering to each relevant table
analyzer = entry['analyzers'][0]
analyzer = entry["analyzers"][0]
for index, (algorithm, header, table) in enumerate(sorted_experiments):
if analyzer == algorithm.fullname(): #applies the sorting
if analyzer == algorithm.fullname(): # applies the sorting
getters = [] #getters for sorting
getters = [] # getters for sorting
tmp_table = copy.deepcopy(table)
for row in tmp_table:
......@@ -210,20 +196,22 @@ class Leaderboard(models.Model):
if isinstance(element, Result):
row[k] = element.value()
# 2. append experiment end date (in seconds) to the end
row.append(-1 * (row[0].end_date-EPOCH).total_seconds())
row.append(-1 * (row[0].end_date - EPOCH).total_seconds())
# replaces experiments with indexes
for i, row in enumerate(table): tmp_table[i][0] = i
for i, row in enumerate(table):
tmp_table[i][0] = i
# get index of columns to use for sorting
for col in entry['columns']:
g = header.index(col['name'].rsplit('.', 1)[1]) + 1
if not col['ascending']:
for row in tmp_table: row[g] *= -1
for col in entry["columns"]:
g = header.index(col["name"].