From f02be24470a8e01549b8250beb02330563f01e74 Mon Sep 17 00:00:00 2001
From: Samuel Gaist <samuel.gaist@idiap.ch>
Date: Fri, 11 Sep 2020 10:50:51 +0200
Subject: [PATCH] [search][all] Pre-commit cleanup

---
 beat/web/search/admin.py       |  170 ++---
 beat/web/search/api.py         |   48 +-
 beat/web/search/apps.py        |   11 +-
 beat/web/search/fields.py      |    1 +
 beat/web/search/models.py      |  206 +++---
 beat/web/search/serializers.py |   90 +--
 beat/web/search/signals.py     |   30 +-
 beat/web/search/utils.py       | 1093 ++++++++++++++++++--------------
 beat/web/search/views.py       |  309 +++++----
 9 files changed, 1082 insertions(+), 876 deletions(-)

diff --git a/beat/web/search/admin.py b/beat/web/search/admin.py
index 2442dc424..eb8773529 100644
--- a/beat/web/search/admin.py
+++ b/beat/web/search/admin.py
@@ -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)
diff --git a/beat/web/search/api.py b/beat/web/search/api.py
index a3863c3e1..5d0d4b5ff 100644
--- a/beat/web/search/api.py
+++ b/beat/web/search/api.py
@@ -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:
diff --git a/beat/web/search/apps.py b/beat/web/search/apps.py
index da7e5f4f5..01745b55e 100644
--- a/beat/web/search/apps.py
+++ b/beat/web/search/apps.py
@@ -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"))
diff --git a/beat/web/search/fields.py b/beat/web/search/fields.py
index 6bf806d4e..fbf2aa17f 100644
--- a/beat/web/search/fields.py
+++ b/beat/web/search/fields.py
@@ -27,5 +27,6 @@
 
 from rest_framework import serializers
 
+
 class DictListField(serializers.ListField):
     child = serializers.DictField()
diff --git a/beat/web/search/models.py b/beat/web/search/models.py
index 74c21542c..57611a75f 100644
--- a/beat/web/search/models.py
+++ b/beat/web/search/models.py
@@ -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"].rsplit(".", 1)[1]) + 1
+                        if not col["ascending"]:
+                            for row in tmp_table:
+                                row[g] *= -1
                         getters.append(g)
 
                     # if there are matching rows, sort by date (latest first)
-                    getters.append(len(tmp_table[0])-1)
+                    getters.append(len(tmp_table[0]) - 1)
 
                     # sort table tmp_table and apply results back
                     tmp_table.sort(key=operator.itemgetter(*getters))
@@ -232,22 +220,21 @@ class Leaderboard(models.Model):
                     table = [table[k[0]] for k in tmp_table]
 
                     # remove unwanted columns
-                    del getters[-1] #remove date element from list
-                    getters.insert(0, 0) #keep experiment pointers
+                    del getters[-1]  # remove date element from list
+                    getters.insert(0, 0)  # keep experiment pointers
                     for j, row in enumerate(table):
-                        table[j] = [v for k,v in enumerate(row) if k in getters]
+                        table[j] = [v for k, v in enumerate(row) if k in getters]
 
                     # remove unwanted headers
-                    del getters[0] #not useful for header manipulation
-                    header = [v for k,v in enumerate(header) if k+1 in getters]
+                    del getters[0]  # not useful for header manipulation
+                    header = [v for k, v in enumerate(header) if k + 1 in getters]
 
                 sorted_experiments[index] = (algorithm, header, table)
 
         return sorted_experiments
 
-
     def table(self):
-        '''Returns the leader board tables for all algorithms'''
+        """Returns the leader board tables for all algorithms"""
 
         retval = []
 
@@ -255,20 +242,22 @@ class Leaderboard(models.Model):
 
             table = []
 
-            for rank in Rank.objects.filter(leaderboard=self, algorithm=algo).distinct().order_by('order'):
-                results = rank.result.order_by('name')
-                if not table: #add header
-                    table.append(['experiment'] + [k.name for k in results])
+            for rank in (
+                Rank.objects.filter(leaderboard=self, algorithm=algo)
+                .distinct()
+                .order_by("order")
+            ):
+                results = rank.result.order_by("name")
+                if not table:  # add header
+                    table.append(["experiment"] + [k.name for k in results])
                 table.append([rank.experiment] + [k.value() for k in results])
 
             retval.append((algo, table))
 
-
         return retval
 
-
     def update_experiments(self):
-        '''Updates internal experiment table, returns ``True`` if changed'''
+        """Updates internal experiment table, returns ``True`` if changed"""
 
         prev_table = self.table()
 
@@ -277,26 +266,27 @@ class Leaderboard(models.Model):
         # at this point, all tables are sorted, set results
         for algorithm, header, table in self.current_experiments():
             for k, row in enumerate(table):
-                r = Rank(leaderboard=self, experiment=row[0],
-                         algorithm=algorithm, order=k)
+                r = Rank(
+                    leaderboard=self, experiment=row[0], algorithm=algorithm, order=k
+                )
                 r.save()
-                for j in row[1:]: r.result.add(j)
+                for j in row[1:]:
+                    r.result.add(j)
 
         return prev_table != self.table()
 
-
     def save(self, *args, **kwargs):
-        '''Overload of Django's built-in'''
+        """Overload of Django's built-in"""
 
         super(Leaderboard, self).save(*args, **kwargs)
 
-        if self.update_experiments(): #changed
+        if self.update_experiments():  # changed
             self.changed = datetime.datetime.now()
             super(Leaderboard, self).save(*args, **kwargs)
 
 
 class Rank(models.Model):
-    '''Keeps experiments ordered on the experiments relationship for searches'''
+    """Keeps experiments ordered on the experiments relationship for searches"""
 
     leaderboard = models.ForeignKey(Leaderboard, on_delete=models.CASCADE)
     experiment = models.ForeignKey(Experiment, on_delete=models.CASCADE)
@@ -304,8 +294,10 @@ class Rank(models.Model):
     order = models.PositiveIntegerField()
     result = models.ManyToManyField(Result)
 
-
     def __str__(self):
 
-        return '%s: [%d] %s' % (self.leaderboard.search.fullname(),
-                                self.order, self.experiment.fullname())
+        return "%s: [%d] %s" % (
+            self.leaderboard.search.fullname(),
+            self.order,
+            self.experiment.fullname(),
+        )
diff --git a/beat/web/search/serializers.py b/beat/web/search/serializers.py
index 0842ca671..01601e485 100644
--- a/beat/web/search/serializers.py
+++ b/beat/web/search/serializers.py
@@ -25,24 +25,22 @@
 #                                                                             #
 ###############################################################################
 
+import simplejson as json
 from rest_framework import serializers
 
-
 from ..common.serializers import VersionableSerializer
 from ..ui.templatetags.markup import restructuredtext
-
-from .models import Search, Leaderboard
 from .fields import DictListField
-
-import simplejson as json
+from .models import Leaderboard
+from .models import Search
 
 
 class SearchResultSerializer(serializers.Serializer):
     name = serializers.SerializerMethodField()
-    description = serializers.CharField(source='short_description')
+    description = serializers.CharField(source="short_description")
 
     def __init__(self, *args, **kwargs):
-        self.name_field = kwargs.pop('name_field', 'fullname')
+        self.name_field = kwargs.pop("name_field", "fullname")
 
         super(SearchResultSerializer, self).__init__(*args, **kwargs)
 
@@ -65,23 +63,31 @@ class SearchSerializer(VersionableSerializer):
 
     class Meta(VersionableSerializer.Meta):
         model = Search
-        default_fields = ['name', 'author', 'user_name', 'is_owner', 'accessibility', 'short_description', 'update_url']
+        default_fields = [
+            "name",
+            "author",
+            "user_name",
+            "is_owner",
+            "accessibility",
+            "short_description",
+            "update_url",
+        ]
 
     def get_user_name(self, obj):
-        return self.context['user'].username
+        return self.context["user"].username
 
     def get_is_owner(self, obj):
-        return self.context['user'] == obj.author
+        return self.context["user"] == obj.author
 
     def get_accessibility(self, obj):
-        (has_access, accessibility) = obj.accessibility_for(self.context['user'])
+        (has_access, accessibility) = obj.accessibility_for(self.context["user"])
         return accessibility
 
     def get_html_description(self, obj):
         d = obj.description
         if len(d) > 0:
             return restructuredtext(d)
-        return ''
+        return ""
 
     def get_update_url(self, obj):
         return obj.get_api_update_url()
@@ -98,53 +104,63 @@ class SearchWriteSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Search
-        fields = ['name', 'short_description', 'description',
-                  'filters', 'settings', 'leaderboard']
+        fields = [
+            "name",
+            "short_description",
+            "description",
+            "filters",
+            "settings",
+            "leaderboard",
+        ]
         default_fields = []
 
     def validate_name(self, name):
         sanitized_name = Search.sanitize_name(name)
-        user = self.context['user']
+        user = self.context["user"]
         if Search.objects.filter(author=user, name=sanitized_name).exists():
-            raise serializers.ValidationError('Name already used')
+            raise serializers.ValidationError("Name already used")
         return sanitized_name
 
     def validate(self, validated_data):
-        if 'description' in validated_data and\
-            not 'short_description' in validated_data:
-            raise serializers.ValidationError('Missing short description')
+        if (
+            "description" in validated_data
+            and "short_description" not in validated_data
+        ):
+            raise serializers.ValidationError("Missing short description")
 
         return validated_data
 
     def create(self, validated_data):
-        user = self.context['user']
+        user = self.context["user"]
         search = Search(author=user, version=1)
-        search.name = validated_data['name']
-        search.filters = json.dumps(validated_data.get('filters'))
-        search.settings = json.dumps(validated_data.get('settings'))
-        search.short_description = validated_data.get('short_description', '')
-        search.description = validated_data.get('description', '')
+        search.name = validated_data["name"]
+        search.filters = json.dumps(validated_data.get("filters"))
+        search.settings = json.dumps(validated_data.get("settings"))
+        search.short_description = validated_data.get("short_description", "")
+        search.description = validated_data.get("description", "")
         search.save()
 
-        #if leaderboard activation was asked, activate the leaderboard
-        if validated_data.get('leaderboard'):
+        # if leaderboard activation was asked, activate the leaderboard
+        if validated_data.get("leaderboard"):
             leaderboard = Leaderboard(search=search)
             leaderboard.notify.add(user)
 
         return search
 
     def update(self, instance, validated_data):
-        if 'filters' in validated_data:
-            instance.filters = json.dumps(validated_data.get('filters'))
-        if 'settings' in validated_data:
-            instance.settings = json.dumps(validated_data.get('settings'))
-        instance.short_description = validated_data.get('short_description', instance.short_description)
-        instance.description = validated_data.get('description', instance.description)
+        if "filters" in validated_data:
+            instance.filters = json.dumps(validated_data.get("filters"))
+        if "settings" in validated_data:
+            instance.settings = json.dumps(validated_data.get("settings"))
+        instance.short_description = validated_data.get(
+            "short_description", instance.short_description
+        )
+        instance.description = validated_data.get("description", instance.description)
         instance.save()
 
-        #if leaderboard activation was asked, activate the leaderboard
-        leaderboard = validated_data.get('leaderboard')
-        if leaderboard is True: #create
+        # if leaderboard activation was asked, activate the leaderboard
+        leaderboard = validated_data.get("leaderboard")
+        if leaderboard is True:  # create
             # for some reason, get_or_create always raises an IntegrityError
             try:
                 obj = Leaderboard.objects.get(search=instance)
@@ -152,7 +168,7 @@ class SearchWriteSerializer(serializers.ModelSerializer):
                 obj = Leaderboard(search=instance)
                 obj.save()
             obj.notify.add(instance.author)
-        elif leaderboard is False and instance.has_leaderboard(): #delete
+        elif leaderboard is False and instance.has_leaderboard():  # delete
             instance.leaderboard.delete()
 
         return instance
diff --git a/beat/web/search/signals.py b/beat/web/search/signals.py
index 73e15b10f..b730aed17 100644
--- a/beat/web/search/signals.py
+++ b/beat/web/search/signals.py
@@ -25,32 +25,34 @@
 #                                                                             #
 ###############################################################################
 
+from django.conf import settings
+from django.contrib.sites.models import Site
+from django.core.mail import EmailMessage
 from django.db import models
 from django.dispatch import receiver
-
-from django.core.mail import EmailMessage
 from django.template.loader import render_to_string
-from django.conf import settings
-from django.contrib.sites.models import Site
 
+from .. import version
 from .models import Leaderboard
 
+
 @receiver(models.signals.pre_delete, sender=Leaderboard)
 def notify_users(sender, instance, **kwargs):
     """Notify users the leaderboard was deleted"""
-    emails = instance.notify.exclude(instance.author).values_list('email', flat=True)
+    emails = instance.notify.exclude(instance.author).values_list("email", flat=True)
     if emails:
-        template_path = 'search/leaderboard_deleted.txt'
-        subject = "Leaderboard \"%s\" was deleted" % instance.search.fullname()
+        current_site = Site.objects.get_current()
+        template_path = "search/leaderboard_deleted.txt"
+        subject = 'Leaderboard "%s" was deleted' % instance.search.fullname()
         mesg = EmailMessage(
             subject.strip(),
-            render_to_string(template_path,
-                             {
-                                 'leaderboard': instance,
-                                 'prev_date': prev_date,
-                                 'beat_version': __version__,
-                                 'site': current_site,
-                             }
+            render_to_string(
+                template_path,
+                {
+                    "leaderboard": instance,
+                    "beat_version": version.__version__,
+                    "site": current_site,
+                },
             ),
             settings.DEFAULT_FROM_EMAIL,
             to=[settings.DEFAULT_FROM_EMAIL],
diff --git a/beat/web/search/utils.py b/beat/web/search/utils.py
index f26a44090..af9793ed8 100644
--- a/beat/web/search/utils.py
+++ b/beat/web/search/utils.py
@@ -25,8 +25,8 @@
 #                                                                             #
 ###############################################################################
 
-import re
 import datetime
+import re
 
 try:
     from functools import reduce
@@ -34,30 +34,27 @@ except ImportError:
     pass
 
 from django.db.models import Q
-from django.db.models.query import QuerySet
 
 UNLIKELY_STRING = "ZaqXsw<>?:{}|!@#$%^&*()-={}"
 
 
-#-------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
 # Helper class to create an AND'ed combination of Q filters
 #
 # It is destined to create filters corresponding to contribution names,
 # containing optional '*' wildcards characters.
-#-------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
 class FilterGenerator(object):
 
-    FILTER_IEXACT      = 0
-    FILTER_ICONTAINS   = 1
+    FILTER_IEXACT = 0
+    FILTER_ICONTAINS = 1
     FILTER_ISTARTSWITH = 2
-    FILTER_IENDSWITH   = 3
-
+    FILTER_IENDSWITH = 3
 
     def __init__(self):
         self.filter = None
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Process a contribution name, optionally containing '*' wildcards
     # characters, and returns the corresponding filter
     #
@@ -70,7 +67,7 @@ class FilterGenerator(object):
     #
     # The 'exact' parameters prevents '*' wildcards to be added at the
     # beginning and/or end of the relevant contribution name parts.
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     def process_contribution_name(self, contribution_name, exact=False):
         self.filter = None
 
@@ -84,8 +81,7 @@ class FilterGenerator(object):
 
         return self.filter
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Process a dataset name, optionally containing '*' wildcards characters,
     # and returns the corresponding filter
     #
@@ -97,11 +93,13 @@ class FilterGenerator(object):
     #
     # The 'exact' parameters prevents '*' wildcards to be added at the
     # beginning and/or end of the relevant dataset name parts.
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     def process_dataset_name(self, dataset_name, exact=False):
         self.filter = None
 
-        (database, version, protocol, dataset) = self.parse_dataset_name(dataset_name, exact)
+        (database, version, protocol, dataset) = self.parse_dataset_name(
+            dataset_name, exact
+        )
 
         self.add(database, FilterGenerator.create_name_filter)
 
@@ -113,8 +111,7 @@ class FilterGenerator(object):
 
         return self.filter
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Parse a contribution name, optionally containing '*' wildcards characters
     #
     # The contribution name can be in one of the following forms:
@@ -129,25 +126,25 @@ class FilterGenerator(object):
     #
     # The 'exact' parameters prevents '*' wildcards to be added at the
     # beginning and/or end of the relevant contribution name parts.
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     def parse_contribution_name(self, contribution_name, exact=False):
-        parts = contribution_name.split('/')
+        parts = contribution_name.split("/")
 
-        author  = None
-        name    = None
+        author = None
+        name = None
         version = None
 
         if len(parts) == 3:
             author = parts[0]
 
-            if not(exact) and (author[0] != '*'):
-                author = '*' + author
+            if not (exact) and (author[0] != "*"):
+                author = "*" + author
 
             name = parts[1]
 
             try:
                 version = int(parts[2])
-            except:
+            except ValueError:
                 pass
 
         elif len(parts) == 2:
@@ -155,31 +152,30 @@ class FilterGenerator(object):
                 version = int(parts[1])
                 name = parts[0]
 
-                if not(exact) and (name[0] != '*'):
-                    name = '*'  + name
-            except:
+                if not (exact) and (name[0] != "*"):
+                    name = "*" + name
+            except ValueError:
                 author = parts[0]
-                if not(exact) and (author[0] != '*'):
-                    author = '*' + author
+                if not (exact) and (author[0] != "*"):
+                    author = "*" + author
 
                 name = parts[1]
-                if not(exact) and (name[-1] != '*'):
-                    name = name + '*'
+                if not (exact) and (name[-1] != "*"):
+                    name = name + "*"
 
         else:
             name = parts[0]
 
-            if not(exact):
-                if name[0] != '*':
-                    name = '*'  + name
+            if not (exact):
+                if name[0] != "*":
+                    name = "*" + name
 
-                if name[-1] != '*':
-                    name = name + '*'
+                if name[-1] != "*":
+                    name = name + "*"
 
         return (author, name, version)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Parse a dataset name, optionally containing '*' wildcards characters
     #
     # The dataset name can be in one of the following forms:
@@ -196,63 +192,62 @@ class FilterGenerator(object):
     #
     # The 'exact' parameters prevents '*' wildcards to be added at the
     # beginning and/or end of the relevant dataset name parts.
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     def parse_dataset_name(self, dataset_name, exact=False):
-        parts = re.split(r'[\.@]', dataset_name.strip(".@"))
+        parts = re.split(r"[\.@]", dataset_name.strip(".@"))
 
         database = None
-        version  = None
+        version = None
         protocol = None
-        dataset  = None
+        dataset = None
 
         if len(parts) >= 3:
             database = parts[0]
-            if not(exact) and (database[0] != '*'):
-                database = '*' + database
+            if not (exact) and (database[0] != "*"):
+                database = "*" + database
 
             protocol = parts[1]
 
-            dataset = '.'.join(parts[2:])
-            if not(exact) and (dataset[-1] != '*'):
-                dataset = dataset + '*'
+            dataset = ".".join(parts[2:])
+            if not (exact) and (dataset[-1] != "*"):
+                dataset = dataset + "*"
 
         elif len(parts) == 2:
             database = parts[0]
-            if not(exact) and (database[0] != '*'):
-                database = '*' + database
+            if not (exact) and (database[0] != "*"):
+                database = "*" + database
 
             protocol = parts[1]
-            if not(exact) and (protocol[-1] != '*'):
-                protocol = protocol + '*'
+            if not (exact) and (protocol[-1] != "*"):
+                protocol = protocol + "*"
 
         else:
             database = parts[0]
 
-            if not(exact):
-                if database[0] != '*':
-                    database = '*'  + database
+            if not (exact):
+                if database[0] != "*":
+                    database = "*" + database
 
-                if database[-1] != '*':
-                    database = database + '*'
+                if database[-1] != "*":
+                    database = database + "*"
 
         if database is not None:
-            parts = database.split('/')
+            parts = database.split("/")
             if len(parts) == 2:
-                if parts[1][-1] == '*':
-                    parts[0] += '*'
+                if parts[1][-1] == "*":
+                    parts[0] += "*"
                     parts[1] = parts[1][:-1]
 
                 database = parts[0]
 
                 try:
                     version = int(parts[1])
-                except:
+                except ValueError:
                     pass
 
         return (database, version, protocol, dataset)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Process a (string) part of a contribution name, and invoke the provided
     # callback with the correct creation information
     #
@@ -263,9 +258,8 @@ class FilterGenerator(object):
     # supplied type.
     #
     # Note: the value can be None, in which case the filter isn't changed.
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     def add(self, value, creation_callback):
-
         def _add(new_filter):
             if self.filter is None:
                 self.filter = new_filter
@@ -275,10 +269,10 @@ class FilterGenerator(object):
         if value is None:
             return
 
-        start = (value[0] == '*')
-        end   = (value[-1] == '*')
+        start = value[0] == "*"
+        end = value[-1] == "*"
 
-        parts = [x for x in value.split('*') if len(x) > 0]
+        parts = [x for x in value.split("*") if len(x) > 0]
 
         if len(parts) == 0:
             return
@@ -305,10 +299,9 @@ class FilterGenerator(object):
             for part in parts[1:-1]:
                 _add(creation_callback(FilterGenerator.FILTER_ICONTAINS, part))
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'author__username__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_author_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -320,10 +313,9 @@ class FilterGenerator(object):
         else:
             return Q(author__username__iexact=value)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'name__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_name_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -335,10 +327,9 @@ class FilterGenerator(object):
         else:
             return Q(name__iexact=value)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'toolchain__author__username__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_toolchain_author_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -350,10 +341,9 @@ class FilterGenerator(object):
         else:
             return Q(toolchain__author__username__iexact=value)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'toolchain__name__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_toolchain_name_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -365,10 +355,9 @@ class FilterGenerator(object):
         else:
             return Q(toolchain__name__iexact=value)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'protocols__name__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_protocol_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -380,10 +369,9 @@ class FilterGenerator(object):
         else:
             return Q(protocols__name__iexact=value)
 
-
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     # Creation callback for 'protocols__sets__name__*'
-    #---------------------------------------------------------------------------
+    # ---------------------------------------------------------------------------
     @staticmethod
     def create_dataset_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
@@ -396,18 +384,17 @@ class FilterGenerator(object):
             return Q(protocols__sets__name__iexact=value)
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def OR(filters):
     return reduce(lambda a, b: a | b, filters)
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_database_filter(database, django_operator):
-
     def _create_database_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
             return Q(referenced_datasets__protocol__database__name__icontains=value)
@@ -438,15 +425,18 @@ def generate_database_filter(database, django_operator):
         else:
             return Q(referenced_datasets__name__iexact=value)
 
-
     generator = FilterGenerator()
 
-    (database, version, protocol, dataset) = generator.parse_dataset_name(database, (django_operator == 'exact'))
+    (database, version, protocol, dataset) = generator.parse_dataset_name(
+        database, (django_operator == "exact")
+    )
 
     generator.add(database, _create_database_filter)
 
     if version is not None:
-        generator.filter = generator.filter & Q(referenced_datasets__protocol__database__version=version)
+        generator.filter = generator.filter & Q(
+            referenced_datasets__protocol__database__version=version
+        )
 
     generator.add(protocol, _create_protocol_filter)
     generator.add(dataset, _create_dataset_filter)
@@ -455,116 +445,139 @@ def generate_database_filter(database, django_operator):
 
 
 def filter_database_name(queryset, operator, value):
-    if operator == 'contains':
-        return queryset.filter(generate_database_filter(value, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_database_filter(value, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_database_filter(value, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_database_filter(value, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_database_filter(x, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_database_filter(x, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_database_filter(x, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_database_filter(x, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_database_filter(value, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_database_filter(value, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_database_filter(value, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_database_filter(value, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_database_filter(x, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_database_filter(x, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_database_filter(x, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_database_filter(x, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_protocol_filter(protocol, django_operator):
-    splitted = re.split(r'[\.@]', protocol)
+    splitted = re.split(r"[\.@]", protocol)
     if len(splitted) <= 2:
-        protocol = '*.' + protocol
+        protocol = "*." + protocol
 
     return generate_database_filter(protocol, django_operator)
 
 
 def filter_protocol_name(queryset, operator, value):
-    if operator == 'contains':
-        return queryset.filter(generate_protocol_filter(value, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_protocol_filter(value, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_protocol_filter(value, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_protocol_filter(value, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_protocol_filter(x, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_protocol_filter(x, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_protocol_filter(x, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_protocol_filter(x, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_protocol_filter(value, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_protocol_filter(value, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_protocol_filter(value, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_protocol_filter(value, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_protocol_filter(x, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_protocol_filter(x, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_protocol_filter(x, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_protocol_filter(x, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_dataset_filter(dataset, django_operator):
-    splitted = re.split(r'[\.@]', dataset)
+    splitted = re.split(r"[\.@]", dataset)
     if len(splitted) == 1:
-        dataset = '*.' + dataset
+        dataset = "*." + dataset
 
     return generate_protocol_filter(dataset, django_operator)
 
 
 def filter_dataset_name(queryset, operator, value):
-    if operator == 'contains':
-        return queryset.filter(generate_dataset_filter(value, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_dataset_filter(value, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_dataset_filter(value, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_dataset_filter(value, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_dataset_filter(x, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_dataset_filter(x, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_dataset_filter(x, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_dataset_filter(x, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_dataset_filter(value, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_dataset_filter(value, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_dataset_filter(value, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_dataset_filter(value, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_dataset_filter(x, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_dataset_filter(x, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_dataset_filter(x, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_dataset_filter(x, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_algorithm_filter(algorithm, analyzer_flag, django_operator):
-
     def _create_algorithm_author_filter(filter_type, value):
         if filter_type == FilterGenerator.FILTER_ICONTAINS:
             return Q(blocks__algorithm__author__username__icontains=value)
@@ -585,10 +598,11 @@ def generate_algorithm_filter(algorithm, analyzer_flag, django_operator):
         else:
             return Q(blocks__algorithm__name__iexact=value)
 
-
     generator = FilterGenerator()
 
-    (author, name, version) = generator.parse_contribution_name(algorithm, (django_operator == 'exact'))
+    (author, name, version) = generator.parse_contribution_name(
+        algorithm, (django_operator == "exact")
+    )
 
     generator.add(author, _create_algorithm_author_filter)
     generator.add(name, _create_algorithm_name_filter)
@@ -603,71 +617,89 @@ def generate_algorithm_filter(algorithm, analyzer_flag, django_operator):
 
 def filter_algorithm_fullname(queryset, operator, value, analyzer):
 
-    if operator == 'contains':
-        return queryset.filter(generate_algorithm_filter(value, analyzer, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_algorithm_filter(value, analyzer, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_algorithm_filter(value, analyzer, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_algorithm_filter(value, analyzer, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_algorithm_filter(x, analyzer, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_algorithm_filter(x, analyzer, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_algorithm_filter(x, analyzer, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_algorithm_filter(x, analyzer, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_algorithm_filter(value, analyzer, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_algorithm_filter(value, analyzer, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_algorithm_filter(value, analyzer, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_algorithm_filter(value, analyzer, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_algorithm_filter(x, analyzer, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_algorithm_filter(x, analyzer, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_algorithm_filter(x, analyzer, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_algorithm_filter(x, analyzer, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def filter_toolchain_author(queryset, operator, value):
-    if operator == 'contains':
+    if operator == "contains":
         return queryset.filter(toolchain__author__username__icontains=value)
 
-    elif operator == 'contains-not':
+    elif operator == "contains-not":
         return queryset.exclude(toolchain__author__username__icontains=value)
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: Q(toolchain__author__username__icontains=x), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: Q(toolchain__author__username__icontains=x), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: Q(toolchain__author__username__icontains=x), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: Q(toolchain__author__username__icontains=x), value))
+        )
 
-    elif operator == 'is':
+    elif operator == "is":
         return queryset.filter(toolchain__author__username__iexact=value)
 
-    elif operator == 'is-not':
+    elif operator == "is-not":
         return queryset.exclude(toolchain__author__username__iexact=value)
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: Q(toolchain__author__username__iexact=x), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: Q(toolchain__author__username__iexact=x), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: Q(toolchain__author__username__iexact=x), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: Q(toolchain__author__username__iexact=x), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_toolchain_filter(toolchain, django_operator):
     generator = FilterGenerator()
 
-    (author, name, version) = generator.parse_contribution_name(toolchain, (django_operator == 'exact'))
+    (author, name, version) = generator.parse_contribution_name(
+        toolchain, (django_operator == "exact")
+    )
 
     generator.add(author, FilterGenerator.create_toolchain_author_filter)
     generator.add(name, FilterGenerator.create_toolchain_name_filter)
@@ -680,164 +712,219 @@ def generate_toolchain_filter(toolchain, django_operator):
 
 def filter_toolchain_fullname(queryset, operator, value):
 
-    if operator == 'contains':
-        return queryset.filter(generate_toolchain_filter(value, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_toolchain_filter(value, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_toolchain_filter(value, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_toolchain_filter(value, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_toolchain_filter(x, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_toolchain_filter(x, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_toolchain_filter(x, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_toolchain_filter(x, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_toolchain_filter(value, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_toolchain_filter(value, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_toolchain_filter(value, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_toolchain_filter(value, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_toolchain_filter(x, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_toolchain_filter(x, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_toolchain_filter(x, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_toolchain_filter(x, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def filter_experiment_author(queryset, operator, value):
-    if operator == 'contains':
+    if operator == "contains":
         return queryset.filter(author__username__icontains=value)
 
-    elif operator == 'contains-not':
+    elif operator == "contains-not":
         return queryset.exclude(author__username__icontains=value)
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: Q(author__username__icontains=x), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: Q(author__username__icontains=x), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: Q(author__username__icontains=x), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: Q(author__username__icontains=x), value))
+        )
 
-    elif operator == 'is':
+    elif operator == "is":
         return queryset.filter(author__username__iexact=value)
 
-    elif operator == 'is-not':
+    elif operator == "is-not":
         return queryset.exclude(author__username__iexact=value)
 
-    elif operator == 'is-any-of':
+    elif operator == "is-any-of":
         return queryset.filter(OR(map(lambda x: Q(author__username__iexact=x), value)))
 
-    elif operator == 'is-not-any-of':
+    elif operator == "is-not-any-of":
         return queryset.exclude(OR(map(lambda x: Q(author__username__iexact=x), value)))
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def generate_experiment_filter(experiment, django_operator):
-    experiment_elems = experiment.split('/')
+    experiment_elems = experiment.split("/")
     if len(experiment_elems) == 5:
-        experiment_authorname, toolchain_authorname, toolchain_name, toolchain_version, experiment_name = experiment_elems
+        (
+            experiment_authorname,
+            toolchain_authorname,
+            toolchain_name,
+            toolchain_version,
+            experiment_name,
+        ) = experiment_elems
         try:
             toolchain_version = int(toolchain_version)
-        except:
+        except ValueError:
             return Q(name__iexact=UNLIKELY_STRING)
-        if django_operator == 'contains':
-            return Q(author__username__icontains=experiment_authorname) & Q(toolchain__author__username__icontains=toolchain_authorname) & \
-                Q(toolchain__name__icontains=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__icontains=experiment_name)
-        elif django_operator == 'exact':
-            return Q(author__username__iexact=experiment_authorname) & Q(toolchain__author__username__iexact=toolchain_authorname) & \
-                Q(toolchain__name__iexact=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__iexact=experiment_name)
+        if django_operator == "contains":
+            return (
+                Q(author__username__icontains=experiment_authorname)
+                & Q(toolchain__author__username__icontains=toolchain_authorname)
+                & Q(toolchain__name__icontains=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__icontains=experiment_name)
+            )
+        elif django_operator == "exact":
+            return (
+                Q(author__username__iexact=experiment_authorname)
+                & Q(toolchain__author__username__iexact=toolchain_authorname)
+                & Q(toolchain__name__iexact=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__iexact=experiment_name)
+            )
     elif len(experiment_elems) == 4:
-        toolchain_authorname, toolchain_name, toolchain_version, experiment_name = experiment_elems
+        (
+            toolchain_authorname,
+            toolchain_name,
+            toolchain_version,
+            experiment_name,
+        ) = experiment_elems
         experiment_authorname = toolchain_authorname
         try:
             toolchain_version = int(toolchain_version)
-        except:
+        except ValueError:
             return Q(name__iexact=UNLIKELY_STRING)
-        if django_operator == 'contains':
-            return Q(toolchain__author__username__icontains=toolchain_authorname) & \
-                Q(toolchain__name__icontains=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__icontains=experiment_name)
-        elif django_operator == 'exact':
-            return Q(toolchain__author__username__iexact=toolchain_authorname) & \
-                Q(toolchain__name__iexact=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__iexact=experiment_name)
+        if django_operator == "contains":
+            return (
+                Q(toolchain__author__username__icontains=toolchain_authorname)
+                & Q(toolchain__name__icontains=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__icontains=experiment_name)
+            )
+        elif django_operator == "exact":
+            return (
+                Q(toolchain__author__username__iexact=toolchain_authorname)
+                & Q(toolchain__name__iexact=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__iexact=experiment_name)
+            )
     elif len(experiment_elems) == 3:
         toolchain_name, toolchain_version, experiment_name = experiment_elems
         try:
             toolchain_version = int(toolchain_version)
-        except:
+        except ValueError:
             return Q(name__iexact=UNLIKELY_STRING)
-        if django_operator == 'contains':
-            return Q(toolchain__name__icontains=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__icontains=experiment_name)
-        elif django_operator == 'exact':
-            return Q(toolchain__name__iexact=toolchain_name) & Q(toolchain__version=toolchain_version) & \
-                Q(name__iexact=experiment_name)
+        if django_operator == "contains":
+            return (
+                Q(toolchain__name__icontains=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__icontains=experiment_name)
+            )
+        elif django_operator == "exact":
+            return (
+                Q(toolchain__name__iexact=toolchain_name)
+                & Q(toolchain__version=toolchain_version)
+                & Q(name__iexact=experiment_name)
+            )
     elif len(experiment_elems) == 2:
         toolchain_version, experiment_name = experiment_elems
         try:
             toolchain_version = int(toolchain_version)
-        except:
+        except ValueError:
             return Q(name__iexact=UNLIKELY_STRING)
-        if django_operator == 'contains':
-            return Q(toolchain__version=toolchain_version) & Q(name__icontains=experiment_name)
-        elif django_operator == 'exact':
-            return Q(toolchain__version=toolchain_version) & Q(name__iexact=experiment_name)
+        if django_operator == "contains":
+            return Q(toolchain__version=toolchain_version) & Q(
+                name__icontains=experiment_name
+            )
+        elif django_operator == "exact":
+            return Q(toolchain__version=toolchain_version) & Q(
+                name__iexact=experiment_name
+            )
     elif len(experiment_elems) == 1:
         experiment_name = experiment_elems[0]
-        if django_operator == 'contains':
+        if django_operator == "contains":
             return Q(name__icontains=experiment_name)
-        elif django_operator == 'exact':
+        elif django_operator == "exact":
             return Q(name__iexact=experiment_name)
     return Q(name__iexact=UNLIKELY_STRING)
 
 
 def filter_experiment(queryset, operator, value):
-    if operator == 'contains':
-        return queryset.filter(generate_experiment_filter(value, 'contains'))
+    if operator == "contains":
+        return queryset.filter(generate_experiment_filter(value, "contains"))
 
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_experiment_filter(value, 'contains'))
+    elif operator == "contains-not":
+        return queryset.exclude(generate_experiment_filter(value, "contains"))
 
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_experiment_filter(x, 'contains'), value)))
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_experiment_filter(x, "contains"), value))
+        )
 
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_experiment_filter(x, 'contains'), value)))
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_experiment_filter(x, "contains"), value))
+        )
 
-    elif operator == 'is':
-        return queryset.filter(generate_experiment_filter(value, 'exact'))
+    elif operator == "is":
+        return queryset.filter(generate_experiment_filter(value, "exact"))
 
-    elif operator == 'is-not':
-        return queryset.exclude(generate_experiment_filter(value, 'exact'))
+    elif operator == "is-not":
+        return queryset.exclude(generate_experiment_filter(value, "exact"))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_experiment_filter(x, 'exact'), value)))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_experiment_filter(x, "exact"), value))
+        )
 
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_experiment_filter(x, 'exact'), value)))
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_experiment_filter(x, "exact"), value))
+        )
 
-    elif operator == 'has-attestation':
+    elif operator == "has-attestation":
         return queryset.filter(attestation__isnull=False)
 
-    elif operator == 'has-no-attestation':
+    elif operator == "has-no-attestation":
         return queryset.filter(attestation__isnull=True)
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def _make_date(value):
@@ -856,11 +943,11 @@ def _make_date(value):
 
     """
 
-    return datetime.datetime.strptime(value, '%Y-%m-%d').date()
+    return datetime.datetime.strptime(value, "%Y-%m-%d").date()
 
 
 def _make_date_range(value):
-  """Creates a datetime.datetime range that spawns the hole day
+    """Creates a datetime.datetime range that spawns the hole day
 
 
     Parameters:
@@ -878,237 +965,305 @@ def _make_date_range(value):
 
   """
 
-  d = _make_date(value)
-  return (datetime.combine(d, datetime.time.min),
-          datetime.combine(d, datetime.time.max))
+    d = _make_date(value)
+    return (
+        datetime.combine(d, datetime.time.min),
+        datetime.combine(d, datetime.time.max),
+    )
 
 
 def filter_experiment_date(queryset, operator, value):
-    if operator == 'is':
+    if operator == "is":
         return queryset.filter(end_date__range=_make_date_range(value))
 
-    elif operator == 'is-not':
+    elif operator == "is-not":
         return queryset.exclude(end_date__range=_make_date_range(value))
 
-    elif operator == 'is-any-of':
-        return queryset.filter(OR([Q(end_date__range=_make_date_range(k)) for k in value]))
-
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR([Q(end_date__range=_make_date_range(k)) for k in value]))
-
-    elif operator == '>':
-        return queryset.filter(end_date__gt=datetime.datetime.combine(_make_date(value), datetime.time.max))
-
-    elif operator == '>=':
-        return queryset.filter(end_date__gte=datetime.datetime.combine(_make_date(value), datetime.time.min))
-
-    elif operator == '<':
-        return queryset.filter(end_date__lt=datetime.datetime.combine(_make_date(value), datetime.time.min))
-
-    elif operator == '<=':
-        return queryset.filter(end_date__lte=datetime.datetime.combine(_make_date(value), datetime.time.max))
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR([Q(end_date__range=_make_date_range(k)) for k in value])
+        )
+
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR([Q(end_date__range=_make_date_range(k)) for k in value])
+        )
+
+    elif operator == ">":
+        return queryset.filter(
+            end_date__gt=datetime.datetime.combine(_make_date(value), datetime.time.max)
+        )
+
+    elif operator == ">=":
+        return queryset.filter(
+            end_date__gte=datetime.datetime.combine(
+                _make_date(value), datetime.time.min
+            )
+        )
+
+    elif operator == "<":
+        return queryset.filter(
+            end_date__lt=datetime.datetime.combine(_make_date(value), datetime.time.min)
+        )
+
+    elif operator == "<=":
+        return queryset.filter(
+            end_date__lte=datetime.datetime.combine(
+                _make_date(value), datetime.time.max
+            )
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def filter_experiment_result(queryset, name, operator, value):
-    if operator == 'is':
-        return queryset.filter(blocks__analyzer=True,
-                               blocks__results__name__iexact=name,
-                               blocks__results__data_value__iexact=value
-                              )
-
-    elif operator == 'is-not':
-        return queryset.exclude(blocks__analyzer=True,
-                                blocks__results__name__iexact=name,
-                                blocks__results__data_value__iexact=value
-                               )
-
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: Q(blocks__results__data_value__iexact=x), value)),
-                               blocks__analyzer=True,
-                               blocks__results__name__iexact=name
-                              )
-
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: Q(blocks__results__data_value__iexact=x), value)),
-                                blocks__analyzer=True,
-                                blocks__results__name__iexact=name
-                               )
-
-    elif operator == '>':
-        return queryset.filter(blocks__analyzer=True,
-                               blocks__results__name__iexact=name,
-                               blocks__results__data_value__gt=value
-                              )
-
-    elif operator == '>=':
-        return queryset.filter(blocks__analyzer=True,
-                               blocks__results__name__iexact=name,
-                               blocks__results__data_value__gte=value
-                              )
-
-    elif operator == '<':
-        return queryset.filter(blocks__analyzer=True,
-                               blocks__results__name__iexact=name,
-                               blocks__results__data_value__lt=value
-                              )
-
-    elif operator == '<=':
-        return queryset.filter(blocks__analyzer=True,
-                               blocks__results__name__iexact=name,
-                               blocks__results__data_value__lte=value
-                              )
+    if operator == "is":
+        return queryset.filter(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__iexact=value,
+        )
+
+    elif operator == "is-not":
+        return queryset.exclude(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__iexact=value,
+        )
+
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: Q(blocks__results__data_value__iexact=x), value)),
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+        )
+
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: Q(blocks__results__data_value__iexact=x), value)),
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+        )
+
+    elif operator == ">":
+        return queryset.filter(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__gt=value,
+        )
+
+    elif operator == ">=":
+        return queryset.filter(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__gte=value,
+        )
+
+    elif operator == "<":
+        return queryset.filter(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__lt=value,
+        )
+
+    elif operator == "<=":
+        return queryset.filter(
+            blocks__analyzer=True,
+            blocks__results__name__iexact=name,
+            blocks__results__data_value__lte=value,
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def filter_any_field(queryset, operator, value):
-    if operator == 'contains':
-        return queryset.filter(generate_database_filter(value, 'contains') |
-                               Q(referenced_datasets__protocol__name__icontains=value) |
-                               Q(referenced_datasets__name__icontains=value) |
-                               generate_algorithm_filter(value, False, 'contains') |
-                               generate_algorithm_filter(value, True, 'contains') |
-                               generate_toolchain_filter(value, 'contains') |
-                               Q(toolchain__author__username__icontains=value) |
-                               Q(author__username__icontains=value) |
-                               generate_experiment_filter(value, 'contains')
-                              )
-
-    elif operator == 'contains-not':
-        return queryset.exclude(generate_database_filter(value, 'contains') |
-                                Q(referenced_datasets__protocol__name__icontains=value) |
-                                Q(referenced_datasets__name__icontains=value) |
-                                generate_algorithm_filter(value, False, 'contains') |
-                                generate_algorithm_filter(value, True, 'contains') |
-                                generate_toolchain_filter(value, 'contains') |
-                                Q(toolchain__author__username__icontains=value) |
-                                Q(author__username__icontains=value) |
-                                generate_experiment_filter(value, 'contains')
-                               )
-
-    elif operator == 'contains-any-of':
-        return queryset.filter(OR(map(lambda x: generate_database_filter(x, 'contains'), value)) |
-                               OR(map(lambda x: Q(referenced_datasets__protocol__name__icontains=x), value)) |
-                               OR(map(lambda x: Q(referenced_datasets__name__icontains=x), value)) |
-                               OR(map(lambda x: generate_algorithm_filter(x, False, 'contains'), value)) |
-                               OR(map(lambda x: generate_algorithm_filter(x, True, 'contains'), value)) |
-                               OR(map(lambda x: generate_toolchain_filter(x, 'contains'), value)) |
-                               OR(map(lambda x: Q(toolchain__author__username__icontains=x), value)) |
-                               OR(map(lambda x: Q(author__username__icontains=x), value)) |
-                               OR(map(lambda x: generate_experiment_filter(x, 'contains'), value))
-                              )
-
-    elif operator == 'contains-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_database_filter(x, 'contains'), value)) |
-                                OR(map(lambda x: Q(referenced_datasets__protocol__name__icontains=x), value)) |
-                                OR(map(lambda x: Q(referenced_datasets__name__icontains=x), value)) |
-                                OR(map(lambda x: generate_algorithm_filter(x, False, 'contains'), value)) |
-                                OR(map(lambda x: generate_algorithm_filter(x, True, 'contains'), value)) |
-                                OR(map(lambda x: generate_toolchain_filter(x, 'contains'), value)) |
-                                OR(map(lambda x: Q(toolchain__author__username__icontains=x), value)) |
-                                OR(map(lambda x: Q(author__username__icontains=x), value)) |
-                                OR(map(lambda x: generate_experiment_filter(x, 'contains'), value))
-                               )
-
-    elif operator == 'is':
-        return queryset.filter(generate_database_filter(value, 'exact') |
-                               Q(referenced_datasets__protocol__name__iexact=value) |
-                               Q(referenced_datasets__name__iexact=value) |
-                               generate_algorithm_filter(value, False, 'exact') |
-                               generate_algorithm_filter(value, True, 'exact') |
-                               generate_toolchain_filter(value, 'exact') |
-                               Q(toolchain__author__username__iexact=value) |
-                               Q(author__username__iexact=value) |
-                               generate_experiment_filter(value, 'exact')
-                              )
-
-    elif operator == 'is-not':
-        return queryset.exclude(generate_database_filter(value, 'exact') |
-                                Q(referenced_datasets__protocol__name__iexact=value) |
-                                Q(referenced_datasets__name__iexact=value) |
-                                generate_algorithm_filter(value, False, 'exact') |
-                                generate_algorithm_filter(value, True, 'exact') |
-                                generate_toolchain_filter(value, 'exact') |
-                                Q(toolchain__author__username__iexact=value) |
-                                Q(author__username__iexact=value) |
-                                generate_experiment_filter(value, 'exact')
-                               )
-
-    elif operator == 'is-any-of':
-        return queryset.filter(OR(map(lambda x: generate_database_filter(x, 'exact'), value)) |
-                               OR(map(lambda x: Q(referenced_datasets__protocol__name__iexact=x), value)) |
-                               OR(map(lambda x: Q(referenced_datasets__name__iexact=x), value)) |
-                               OR(map(lambda x: generate_algorithm_filter(x, False, 'exact'), value)) |
-                               OR(map(lambda x: generate_algorithm_filter(x, True, 'exact'), value)) |
-                               OR(map(lambda x: generate_toolchain_filter(x, 'exact'), value)) |
-                               OR(map(lambda x: Q(toolchain__author__username__iexact=x), value)) |
-                               OR(map(lambda x: Q(author__username__iexact=x), value)) |
-                               OR(map(lambda x: generate_experiment_filter(x, 'exact'), value))
-                              )
-
-    elif operator == 'is-not-any-of':
-        return queryset.exclude(OR(map(lambda x: generate_database_filter(x, 'exact'), value)) |
-                                OR(map(lambda x: Q(referenced_datasets__protocol__name__iexact=x), value)) |
-                                OR(map(lambda x: Q(referenced_datasets__name__iexact=x), value)) |
-                                OR(map(lambda x: generate_algorithm_filter(x, False, 'exact'), value)) |
-                                OR(map(lambda x: generate_algorithm_filter(x, True, 'exact'), value)) |
-                                OR(map(lambda x: generate_toolchain_filter(x, 'exact'), value)) |
-                                OR(map(lambda x: Q(toolchain__author__username__iexact=x), value)) |
-                                OR(map(lambda x: Q(author__username__iexact=x), value)) |
-                                OR(map(lambda x: generate_experiment_filter(x, 'exact'), value))
-                               )
+    if operator == "contains":
+        return queryset.filter(
+            generate_database_filter(value, "contains")
+            | Q(referenced_datasets__protocol__name__icontains=value)
+            | Q(referenced_datasets__name__icontains=value)
+            | generate_algorithm_filter(value, False, "contains")
+            | generate_algorithm_filter(value, True, "contains")
+            | generate_toolchain_filter(value, "contains")
+            | Q(toolchain__author__username__icontains=value)
+            | Q(author__username__icontains=value)
+            | generate_experiment_filter(value, "contains")
+        )
+
+    elif operator == "contains-not":
+        return queryset.exclude(
+            generate_database_filter(value, "contains")
+            | Q(referenced_datasets__protocol__name__icontains=value)
+            | Q(referenced_datasets__name__icontains=value)
+            | generate_algorithm_filter(value, False, "contains")
+            | generate_algorithm_filter(value, True, "contains")
+            | generate_toolchain_filter(value, "contains")
+            | Q(toolchain__author__username__icontains=value)
+            | Q(author__username__icontains=value)
+            | generate_experiment_filter(value, "contains")
+        )
+
+    elif operator == "contains-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_database_filter(x, "contains"), value))
+            | OR(
+                map(
+                    lambda x: Q(referenced_datasets__protocol__name__icontains=x), value
+                )
+            )
+            | OR(map(lambda x: Q(referenced_datasets__name__icontains=x), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, False, "contains"), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, True, "contains"), value))
+            | OR(map(lambda x: generate_toolchain_filter(x, "contains"), value))
+            | OR(map(lambda x: Q(toolchain__author__username__icontains=x), value))
+            | OR(map(lambda x: Q(author__username__icontains=x), value))
+            | OR(map(lambda x: generate_experiment_filter(x, "contains"), value))
+        )
+
+    elif operator == "contains-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_database_filter(x, "contains"), value))
+            | OR(
+                map(
+                    lambda x: Q(referenced_datasets__protocol__name__icontains=x), value
+                )
+            )
+            | OR(map(lambda x: Q(referenced_datasets__name__icontains=x), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, False, "contains"), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, True, "contains"), value))
+            | OR(map(lambda x: generate_toolchain_filter(x, "contains"), value))
+            | OR(map(lambda x: Q(toolchain__author__username__icontains=x), value))
+            | OR(map(lambda x: Q(author__username__icontains=x), value))
+            | OR(map(lambda x: generate_experiment_filter(x, "contains"), value))
+        )
+
+    elif operator == "is":
+        return queryset.filter(
+            generate_database_filter(value, "exact")
+            | Q(referenced_datasets__protocol__name__iexact=value)
+            | Q(referenced_datasets__name__iexact=value)
+            | generate_algorithm_filter(value, False, "exact")
+            | generate_algorithm_filter(value, True, "exact")
+            | generate_toolchain_filter(value, "exact")
+            | Q(toolchain__author__username__iexact=value)
+            | Q(author__username__iexact=value)
+            | generate_experiment_filter(value, "exact")
+        )
+
+    elif operator == "is-not":
+        return queryset.exclude(
+            generate_database_filter(value, "exact")
+            | Q(referenced_datasets__protocol__name__iexact=value)
+            | Q(referenced_datasets__name__iexact=value)
+            | generate_algorithm_filter(value, False, "exact")
+            | generate_algorithm_filter(value, True, "exact")
+            | generate_toolchain_filter(value, "exact")
+            | Q(toolchain__author__username__iexact=value)
+            | Q(author__username__iexact=value)
+            | generate_experiment_filter(value, "exact")
+        )
+
+    elif operator == "is-any-of":
+        return queryset.filter(
+            OR(map(lambda x: generate_database_filter(x, "exact"), value))
+            | OR(map(lambda x: Q(referenced_datasets__protocol__name__iexact=x), value))
+            | OR(map(lambda x: Q(referenced_datasets__name__iexact=x), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, False, "exact"), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, True, "exact"), value))
+            | OR(map(lambda x: generate_toolchain_filter(x, "exact"), value))
+            | OR(map(lambda x: Q(toolchain__author__username__iexact=x), value))
+            | OR(map(lambda x: Q(author__username__iexact=x), value))
+            | OR(map(lambda x: generate_experiment_filter(x, "exact"), value))
+        )
+
+    elif operator == "is-not-any-of":
+        return queryset.exclude(
+            OR(map(lambda x: generate_database_filter(x, "exact"), value))
+            | OR(map(lambda x: Q(referenced_datasets__protocol__name__iexact=x), value))
+            | OR(map(lambda x: Q(referenced_datasets__name__iexact=x), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, False, "exact"), value))
+            | OR(map(lambda x: generate_algorithm_filter(x, True, "exact"), value))
+            | OR(map(lambda x: generate_toolchain_filter(x, "exact"), value))
+            | OR(map(lambda x: Q(toolchain__author__username__iexact=x), value))
+            | OR(map(lambda x: Q(author__username__iexact=x), value))
+            | OR(map(lambda x: generate_experiment_filter(x, "exact"), value))
+        )
 
     return queryset
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def apply_filter(queryset, filter_entry):
-    context = filter_entry['context']
-    if context == 'database-name':
-        return filter_database_name(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'protocol-name':
-        return filter_protocol_name(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'dataset-name':
-        return filter_dataset_name(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'algorithm':
-        return filter_algorithm_fullname(queryset, filter_entry['operator'], filter_entry['value'], False)
-
-    elif context == 'analyzer':
-        return filter_algorithm_fullname(queryset, filter_entry['operator'], filter_entry['value'], True)
-
-    elif context == 'toolchain-author':
-        return filter_toolchain_author(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'toolchain':
-        return filter_toolchain_fullname(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'experiment-author':
-        return filter_experiment_author(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'experiment':
-        return filter_experiment(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'experiment-date':
-        return filter_experiment_date(queryset, filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'experiment-result':
-        return filter_experiment_result(queryset, filter_entry['name'],
-                                        filter_entry['operator'], filter_entry['value'])
-
-    elif context == 'any-field':
-        return filter_any_field(queryset, filter_entry['operator'], filter_entry['value'])
+    context = filter_entry["context"]
+    if context == "database-name":
+        return filter_database_name(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "protocol-name":
+        return filter_protocol_name(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "dataset-name":
+        return filter_dataset_name(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "algorithm":
+        return filter_algorithm_fullname(
+            queryset, filter_entry["operator"], filter_entry["value"], False
+        )
+
+    elif context == "analyzer":
+        return filter_algorithm_fullname(
+            queryset, filter_entry["operator"], filter_entry["value"], True
+        )
+
+    elif context == "toolchain-author":
+        return filter_toolchain_author(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "toolchain":
+        return filter_toolchain_fullname(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "experiment-author":
+        return filter_experiment_author(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "experiment":
+        return filter_experiment(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "experiment-date":
+        return filter_experiment_date(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
+
+    elif context == "experiment-result":
+        return filter_experiment_result(
+            queryset,
+            filter_entry["name"],
+            filter_entry["operator"],
+            filter_entry["value"],
+        )
+
+    elif context == "any-field":
+        return filter_any_field(
+            queryset, filter_entry["operator"], filter_entry["value"]
+        )
     else:
-        raise ValueError('Unkown context %s' % context)
+        raise ValueError("Unkown context %s" % context)
diff --git a/beat/web/search/views.py b/beat/web/search/views.py
index e4639812d..f93c6d43b 100644
--- a/beat/web/search/views.py
+++ b/beat/web/search/views.py
@@ -25,27 +25,26 @@
 #                                                                             #
 ###############################################################################
 
-from django.http import Http404
-from django.shortcuts import render, redirect
-from django.shortcuts import get_object_or_404
+import datetime
+
+import simplejson as json
 from django.conf import settings
-from django.contrib.auth.models import User
-from django.db.models import Count
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
+from django.http import Http404
+from django.shortcuts import get_object_or_404
+from django.shortcuts import redirect
+from django.shortcuts import render
 
-from .models import Search
-from .utils import apply_filter
-
+from ..databases.models import DatabaseProtocol
+from ..databases.models import DatabaseSet
+from ..experiments.models import Block
+from ..experiments.models import Experiment
 from ..team.models import Team
-from ..ui.templatetags.markup import restructuredtext
-from ..experiments.models import Experiment, Block
-from ..algorithms.models import Algorithm
-from ..databases.models import DatabaseProtocol, DatabaseSet
 from ..toolchains.models import Toolchain
-
-import datetime
-import simplejson as json
+from .models import Search
+from .utils import apply_filter
 
 
 def search_experiments(user, filters, time_delta=None):
@@ -75,13 +74,14 @@ def search_experiments(user, filters, time_delta=None):
     """
 
     results = {
-        'experiments':      [],
-        'common_toolchains':[],
-        'common_protocols': [],
-        'common_analyzers': [],
+        "experiments": [],
+        "common_toolchains": [],
+        "common_protocols": [],
+        "common_analyzers": [],
     }
 
-    if len(filters) == 0: return results
+    if len(filters) == 0:
+        return results
 
     # Use the experiment filters
     experiments = Experiment.objects.for_user(user, True).filter(status=Experiment.DONE)
@@ -104,7 +104,8 @@ def search_experiments(user, filters, time_delta=None):
 
     # All used toolchains
     toolchains = Toolchain.objects.filter(experiments__in=experiments).distinct()
-    if toolchains.count() == 1: results['common_toolchains'] = toolchains
+    if toolchains.count() == 1:
+        results["common_toolchains"] = toolchains
 
     # Dictionary analyzer (algorithm) -> blocks in each experiment
     # The issue: for each experiment, the analyzer block name and associated
@@ -152,9 +153,11 @@ def search_experiments(user, filters, time_delta=None):
 
     # This works if the toolchain is the same or very similar (in terms of
     # block names). Any number of matching blocks is captured.
-    blocks = blocks__in=Block.objects.filter(analyzer=True, experiment__in=experiments)
+    blocks = Block.objects.filter(analyzer=True, experiment__in=experiments)
 
-    ordered_blocks = blocks.order_by('name', 'algorithm__author__username', 'algorithm__name', 'algorithm__version')
+    ordered_blocks = blocks.order_by(
+        "name", "algorithm__author__username", "algorithm__name", "algorithm__version"
+    )
     unused_blocks = []
     blocks_by_name = {}
     for b in ordered_blocks:
@@ -165,7 +168,7 @@ def search_experiments(user, filters, time_delta=None):
             # full match, algorithm is a common analyzer across all experiments
             # n.b.: because block names are unique within experiments the above
             # equality works fine.
-            results['common_analyzers'].append((algorithms.pop(), elements))
+            results["common_analyzers"].append((algorithms.pop(), elements))
 
         # else: blocks with the same name use different algorithms
         else:
@@ -180,25 +183,38 @@ def search_experiments(user, filters, time_delta=None):
         blocks_by_algorithm.setdefault(block.algorithm, []).append(block)
     for algorithm, algo_blocks in blocks_by_algorithm.items():
         uniq_experiments = set([k.experiment for k in algo_blocks])
-        if len(algo_blocks) == len(experiments) and \
-                len(uniq_experiments) == len(experiments):
-            results['common_analyzers'].append((algorithm, algo_blocks))
+        if len(algo_blocks) == len(experiments) and len(uniq_experiments) == len(
+            experiments
+        ):
+            results["common_analyzers"].append((algorithm, algo_blocks))
 
     # Protocols
-    protocols = DatabaseProtocol.objects.filter(sets__in=DatabaseSet.objects.filter(experiments__in=experiments)).distinct()
+    protocols = DatabaseProtocol.objects.filter(
+        sets__in=DatabaseSet.objects.filter(experiments__in=experiments)
+    ).distinct()
 
     if protocols.count() == 1:
-        results['common_protocols'] = protocols
-    else: #do we have the same number of protocols everywhere?
+        results["common_protocols"] = protocols
+    else:  # do we have the same number of protocols everywhere?
         # calculates the distinct protocols per experiment
-        if all([DatabaseProtocol.objects.filter(sets__in=DatabaseSet.objects.filter(experiments__in=[k])).distinct().count() == protocols.count() for k in experiments]):
-            results['common_protocols'] = protocols
-
-    results['experiments'] = experiments
+        if all(
+            [
+                DatabaseProtocol.objects.filter(
+                    sets__in=DatabaseSet.objects.filter(experiments__in=[k])
+                )
+                .distinct()
+                .count()
+                == protocols.count()
+                for k in experiments
+            ]
+        ):
+            results["common_protocols"] = protocols
+
+    results["experiments"] = experiments
     return results
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def filters_from_query(query):
@@ -207,40 +223,41 @@ def filters_from_query(query):
     filters = []
     any_fields = []
 
-    if not query.strip(): return filters #empty
+    if not query.strip():
+        return filters  # empty
 
     def _operator_chooser(arr):
-        return 'contains' if len(arr) == 1 else 'contains-any-of'
+        return "contains" if len(arr) == 1 else "contains-any-of"
 
     def _value_chooser(arr):
         return arr[0] if len(arr) == 1 else arr
 
     def _make_context(name, entries):
         return {
-            'context': name,
-                'operator': _operator_chooser(entries),
-                'value': _value_chooser(entries),
-                'name': None,
+            "context": name,
+            "operator": _operator_chooser(entries),
+            "value": _value_chooser(entries),
+            "name": None,
         }
 
     keywords = [x.strip() for x in query.split() if x.strip()]
 
     for keyword in keywords:
 
-        offset = keyword.find(':')
+        offset = keyword.find(":")
         if offset != -1:
             command = keyword[:offset]
-            entries = [x.strip() for x in keyword[offset+1:].split(',')]
+            entries = [x.strip() for x in keyword[offset + 1 :].split(",")]
             entries = [x for x in entries if x]
-            if command in ['db', 'database']:
-                filters.append(_make_context('database-name', entries))
-            elif command in ['tc', 'toolchain']:
-                filters.append(_make_context('toolchain', entries))
-            elif command in ['algo', 'algorithm']:
-                filters.append(_make_context('algorithm', entries))
-            elif command == 'analyzer':
-                filters.append(_make_context('analyzer', entries))
-            elif command == 'type':
+            if command in ["db", "database"]:
+                filters.append(_make_context("database-name", entries))
+            elif command in ["tc", "toolchain"]:
+                filters.append(_make_context("toolchain", entries))
+            elif command in ["algo", "algorithm"]:
+                filters.append(_make_context("algorithm", entries))
+            elif command == "analyzer":
+                filters.append(_make_context("analyzer", entries))
+            elif command == "type":
                 continue
             else:
                 any_fields.extend(entries)
@@ -248,139 +265,144 @@ def filters_from_query(query):
             any_fields.append(keyword)
 
     if any_fields:
-        filters.append({
-            'context': 'any-field',
-            'operator': 'contains-any-of',
-            'value': any_fields,
-            'name': None,
-        })
+        filters.append(
+            {
+                "context": "any-field",
+                "operator": "contains-any-of",
+                "value": any_fields,
+                "name": None,
+            }
+        )
 
     return filters
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def search(request):
     """Casual search request"""
 
-    filters = '[]' #by default, no filters, display all visible experiments
-    display_settings = [] #by default, no special settings
+    filters = "[]"  # by default, no filters, display all visible experiments
+    display_settings = []  # by default, no special settings
 
     # A sequence of filter overrides that must be respected
-    if 'query' in request.GET:
-        query = request.GET['query'].strip()
+    if "query" in request.GET:
+        query = request.GET["query"].strip()
         filters = json.dumps(filters_from_query(query))
 
-    if 'query' in request.POST: #overrules the GET request
-        query = request.POST['query'].strip()
+    if "query" in request.POST:  # overrules the GET request
+        query = request.POST["query"].strip()
         filters = json.dumps(filters_from_query(query))
 
-    if 'filters' in request.POST: #overrules the other two
-        filters = request.POST['filters'].strip()
+    if "filters" in request.POST:  # overrules the other two
+        filters = request.POST["filters"].strip()
 
-    if 'settings' in request.POST: #overrules the other two
-        display_settings = request.POST['settings'].strip()
+    if "settings" in request.POST:  # overrules the other two
+        display_settings = request.POST["settings"].strip()
 
-    return render(request,
-                  'search/view.html',
-                  dict(
-                      search=None,
-                      owner=False,
-                      filters=filters,
-                      settings=display_settings,
-                      results=search_experiments(request.user, json.loads(filters)),
-                      URL_PREFIX=settings.URL_PREFIX,
-                  ))
+    return render(
+        request,
+        "search/view.html",
+        dict(
+            search=None,
+            owner=False,
+            filters=filters,
+            settings=display_settings,
+            results=search_experiments(request.user, json.loads(filters)),
+            URL_PREFIX=settings.URL_PREFIX,
+        ),
+    )
 
 
-#------------------------------------------------
+# ------------------------------------------------
 
 
 def view(request, author_name, query_name):
     """Stored search request"""
 
     # get the query from the DB
-    obj = get_object_or_404(Search,
-                            author__username = author_name,
-                            name = query_name)
+    obj = get_object_or_404(Search, author__username=author_name, name=query_name)
 
     # makes sure that the current user has access to it
     has_access, _ = obj.accessibility_for(request.user)
 
-    if not has_access: raise Http404()
+    if not has_access:
+        raise Http404()
 
     # user requests a filter update on a saved search, overrides defaults
-    if 'filters' in request.POST:
-        filters = request.POST['filters'].strip()
-    else: #use the obj filters
+    if "filters" in request.POST:
+        filters = request.POST["filters"].strip()
+    else:  # use the obj filters
         filters = obj.filters
 
-    if 'settings' in request.POST:
-        display_settings = request.POST['settings'].strip()
-    else: #use the obj settings
+    if "settings" in request.POST:
+        display_settings = request.POST["settings"].strip()
+    else:  # use the obj settings
         display_settings = obj.settings
 
     # Users the object can be shared with
-    users = User.objects.exclude(username__in=settings.ACCOUNTS_TO_EXCLUDE_FROM_TEAMS).order_by('username')
+    users = User.objects.exclude(
+        username__in=settings.ACCOUNTS_TO_EXCLUDE_FROM_TEAMS
+    ).order_by("username")
 
-    return render(request,
-                  'search/view.html',
-                  {
-                      'search': obj,
-                      'owner': (request.user == obj.author),
-                      'filters': filters,
-                      'settings': display_settings,
-                      'results': search_experiments(request.user, json.loads(filters)),
-                      'URL_PREFIX': settings.URL_PREFIX,
-                      'users': users,
-                      'teams': Team.objects.for_user(request.user, True)
-                  })
+    return render(
+        request,
+        "search/view.html",
+        {
+            "search": obj,
+            "owner": (request.user == obj.author),
+            "filters": filters,
+            "settings": display_settings,
+            "results": search_experiments(request.user, json.loads(filters)),
+            "URL_PREFIX": settings.URL_PREFIX,
+            "users": users,
+            "teams": Team.objects.for_user(request.user, True),
+        },
+    )
 
 
-#----------------------------------------------------------
+# ----------------------------------------------------------
 
 
 def ls(request, author_name):
-    '''List all accessible searches to the request user'''
+    """List all accessible searches 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)
 
     # orders searchs so that the latest information is displayed first
-    objects = Search.objects.from_author_and_public(request.user,
-                                                    author_name).order_by('-creation_date')
+    objects = Search.objects.from_author_and_public(request.user, author_name).order_by(
+        "-creation_date"
+    )
 
-    return render(request,
-                  'search/list.html',
-                  dict(
-                      objects=objects,
-                      author=author,
-                      owner=(request.user==author),
-                  ))
+    return render(
+        request,
+        "search/list.html",
+        dict(objects=objects, author=author, owner=(request.user == author),),
+    )
 
 
-#----------------------------------------------------------
+# ----------------------------------------------------------
 
 
 def public_ls(request):
-    '''List all public searches'''
+    """List all public searches"""
 
     # orders searchs so that the latest information is displayed first
-    objects = Search.objects.public().order_by('-creation_date')
+    objects = Search.objects.public().order_by("-creation_date")
 
-    return render(request,
-                  'search/list.html',
-                  dict(
-                      objects=objects,
-                      author=request.user,
-                      owner=False,
-                  ))
+    return render(
+        request,
+        "search/list.html",
+        dict(objects=objects, author=request.user, owner=False,),
+    )
 
 
-#----------------------------------------------------------
+# ----------------------------------------------------------
 
 
 @login_required
@@ -388,14 +410,13 @@ def notify(request, author_name, query_name):
     """Toggles notification for user"""
 
     # get the query from the DB
-    obj = get_object_or_404(Search,
-                            author__username = author_name,
-                            name = query_name)
+    obj = get_object_or_404(Search, author__username=author_name, name=query_name)
 
     # makes sure that the current user has access to it
     has_access, _ = obj.accessibility_for(request.user)
 
-    if not has_access: raise Http404()
+    if not has_access:
+        raise Http404()
 
     if not obj.has_leaderboard():
         # user page is outdated, reload it
@@ -403,12 +424,30 @@ def notify(request, author_name, query_name):
 
     if obj.leaderboard.notify.filter(id=request.user.id).exists():
         obj.leaderboard.notify.remove(request.user)
-        messages.success(request, "Successfuly unsubscribed %s %s (%s) from leaderboard %s" % (request.user.first_name, request.user.last_name, request.user.username, obj))
+        messages.success(
+            request,
+            "Successfuly unsubscribed %s %s (%s) from leaderboard %s"
+            % (
+                request.user.first_name,
+                request.user.last_name,
+                request.user.username,
+                obj,
+            ),
+        )
     else:
         obj.leaderboard.notify.add(request.user)
-        messages.success(request, "Successfuly subscribed %s %s (%s) to leaderboard %s" % (request.user.first_name, request.user.last_name, request.user.username, obj))
-
-    if 'HTTP_REFERER' in request.META:
-        return redirect(request.META['HTTP_REFERER'])
+        messages.success(
+            request,
+            "Successfuly subscribed %s %s (%s) to leaderboard %s"
+            % (
+                request.user.first_name,
+                request.user.last_name,
+                request.user.username,
+                obj,
+            ),
+        )
+
+    if "HTTP_REFERER" in request.META:
+        return redirect(request.META["HTTP_REFERER"])
 
     return redirect(obj)
-- 
GitLab