diff --git a/openlobby/core/api/mutations.py b/openlobby/core/api/mutations.py
index a0e10121aacde0e9cdbbf958d8a6d90b5465a758..4c92f8ec6cdba1dfc792a5935ff0c2af279f7726 100644
--- a/openlobby/core/api/mutations.py
+++ b/openlobby/core/api/mutations.py
@@ -20,7 +20,6 @@ STATE_LENGTH = 48
 
 
 class Login(relay.ClientIDMutation):
-
     class Input:
         openid_uid = graphene.String(required=True)
         redirect_uri = graphene.String(required=True)
@@ -29,8 +28,8 @@ class Login(relay.ClientIDMutation):
 
     @classmethod
     def mutate_and_get_payload(cls, root, info, **input):
-        openid_uid = input['openid_uid']
-        app_redirect_uri = input['redirect_uri']
+        openid_uid = input["openid_uid"]
+        app_redirect_uri = input["redirect_uri"]
 
         # prepare OpenID client
         issuer = discover_issuer(openid_uid)
@@ -50,8 +49,12 @@ class Login(relay.ClientIDMutation):
         state = rndstr(STATE_LENGTH)
 
         # save login attempt
-        LoginAttempt.objects.create(state=state, openid_client=openid_client_obj,
-            app_redirect_uri=app_redirect_uri, openid_uid=openid_uid)
+        LoginAttempt.objects.create(
+            state=state,
+            openid_client=openid_client_obj,
+            app_redirect_uri=app_redirect_uri,
+            openid_uid=openid_uid,
+        )
 
         # get OpenID authorization url
         authorization_url = get_authorization_url(client, state)
@@ -60,7 +63,6 @@ class Login(relay.ClientIDMutation):
 
 
 class LoginByShortcut(relay.ClientIDMutation):
-
     class Input:
         shortcut_id = relay.GlobalID(required=True)
         redirect_uri = graphene.String(required=True)
@@ -69,8 +71,8 @@ class LoginByShortcut(relay.ClientIDMutation):
 
     @classmethod
     def mutate_and_get_payload(cls, root, info, **input):
-        shortcut_id = input['shortcut_id']
-        app_redirect_uri = input['redirect_uri']
+        shortcut_id = input["shortcut_id"]
+        app_redirect_uri = input["redirect_uri"]
 
         # prepare OpenID client
         type, id = from_global_id(shortcut_id)
@@ -81,8 +83,11 @@ class LoginByShortcut(relay.ClientIDMutation):
         state = rndstr(STATE_LENGTH)
 
         # save login attempt
-        LoginAttempt.objects.create(state=state, openid_client=openid_client_obj,
-            app_redirect_uri=app_redirect_uri)
+        LoginAttempt.objects.create(
+            state=state,
+            openid_client=openid_client_obj,
+            app_redirect_uri=app_redirect_uri,
+        )
 
         # get OpenID authorization url
         authorization_url = get_authorization_url(client, state)
@@ -100,7 +105,6 @@ class Logout(relay.ClientIDMutation):
 
 
 class CreateReport(relay.ClientIDMutation):
-
     class Input:
         title = graphene.String(required=True)
         body = graphene.String(required=True)
@@ -116,27 +120,26 @@ class CreateReport(relay.ClientIDMutation):
     @classmethod
     def mutate_and_get_payload(cls, root, info, **input):
         if not info.context.user.is_authenticated:
-            raise Exception('User must be logged in to perform this mutation.')
+            raise Exception("User must be logged in to perform this mutation.")
 
         author = info.context.user
 
         report = Report.objects.create(
             author=author,
-            date=input.get('date'),
-            title=strip_all_tags(input.get('title', '')),
-            body=strip_all_tags(input.get('body', '')),
-            received_benefit=strip_all_tags(input.get('received_benefit', '')),
-            provided_benefit=strip_all_tags(input.get('provided_benefit', '')),
-            our_participants=strip_all_tags(input.get('our_participants', '')),
-            other_participants=strip_all_tags(input.get('other_participants', '')),
-            is_draft=input.get('is_draft'),
+            date=input.get("date"),
+            title=strip_all_tags(input.get("title", "")),
+            body=strip_all_tags(input.get("body", "")),
+            received_benefit=strip_all_tags(input.get("received_benefit", "")),
+            provided_benefit=strip_all_tags(input.get("provided_benefit", "")),
+            our_participants=strip_all_tags(input.get("our_participants", "")),
+            other_participants=strip_all_tags(input.get("other_participants", "")),
+            is_draft=input.get("is_draft"),
         )
 
         return CreateReport(report=types.Report.from_db(report))
 
 
 class UpdateReport(relay.ClientIDMutation):
-
     class Input:
         id = graphene.ID(required=True)
         title = graphene.String(required=True)
@@ -153,32 +156,36 @@ class UpdateReport(relay.ClientIDMutation):
     @classmethod
     def mutate_and_get_payload(cls, root, info, **input):
         if not info.context.user.is_authenticated:
-            raise Exception('User must be logged in to perform this mutation.')
+            raise Exception("User must be logged in to perform this mutation.")
 
         author = info.context.user
-        type, id = from_global_id(input.get('id'))
+        type, id = from_global_id(input.get("id"))
 
         try:
-            report = Report.objects.select_related('author').get(id=id, author_id=author.id)
+            report = Report.objects.select_related("author").get(
+                id=id, author_id=author.id
+            )
         except Report.DoesNotExist:
-            raise Exception('Viewer is not the Author of this Report or Report does not exist.')
+            raise Exception(
+                "Viewer is not the Author of this Report or Report does not exist."
+            )
 
-        is_draft = input.get('is_draft')
+        is_draft = input.get("is_draft")
 
         if is_draft and not report.is_draft:
-            raise Exception('You cannot update published Report with draft.')
+            raise Exception("You cannot update published Report with draft.")
 
         # TODO updating published report older than like a hour should create
         # new revision in history of report
 
         report.published = arrow.utcnow().datetime
-        report.date = input.get('date')
-        report.title = strip_all_tags(input.get('title', ''))
-        report.body = strip_all_tags(input.get('body', ''))
-        report.received_benefit = strip_all_tags(input.get('received_benefit', ''))
-        report.provided_benefit = strip_all_tags(input.get('provided_benefit', ''))
-        report.our_participants = strip_all_tags(input.get('our_participants', ''))
-        report.other_participants = strip_all_tags(input.get('other_participants', ''))
+        report.date = input.get("date")
+        report.title = strip_all_tags(input.get("title", ""))
+        report.body = strip_all_tags(input.get("body", ""))
+        report.received_benefit = strip_all_tags(input.get("received_benefit", ""))
+        report.provided_benefit = strip_all_tags(input.get("provided_benefit", ""))
+        report.our_participants = strip_all_tags(input.get("our_participants", ""))
+        report.other_participants = strip_all_tags(input.get("other_participants", ""))
         report.is_draft = is_draft
         report.save()
 
diff --git a/openlobby/core/api/paginator.py b/openlobby/core/api/paginator.py
index ea7b05ae39935f072045bd4cb1ae31bbd8a12eff..9e0db12c12d9a5f054e8189053c98e29ccf493f1 100644
--- a/openlobby/core/api/paginator.py
+++ b/openlobby/core/api/paginator.py
@@ -10,16 +10,24 @@ class MissingBeforeValueError(Exception):
 
 
 def encode_cursor(num):
-    return base64.b64encode(str(num).encode('utf-8')).decode('utf-8')
+    return base64.b64encode(str(num).encode("utf-8")).decode("utf-8")
 
 
 def decode_cursor(cursor):
-    return int(base64.b64decode(cursor).decode('utf-8'))
+    return int(base64.b64decode(cursor).decode("utf-8"))
 
 
 class Paginator:
-
-    def __init__(self, *, first=None, after=None, last=None, before=None, per_page=PER_PAGE, **kwargs):
+    def __init__(
+        self,
+        *,
+        first=None,
+        after=None,
+        last=None,
+        before=None,
+        per_page=PER_PAGE,
+        **kwargs
+    ):
         self.per_page = per_page
 
         slice_from = 0
@@ -32,7 +40,9 @@ class Paginator:
 
         elif last is not None:
             if before is None:
-                raise MissingBeforeValueError('Pagination "last" works only in combination with "before" argument.')
+                raise MissingBeforeValueError(
+                    'Pagination "last" works only in combination with "before" argument.'
+                )
 
             slice_to = decode_cursor(before) - 1
             slice_from = slice_to - last
@@ -62,8 +72,12 @@ class Paginator:
             if self.slice_to < total:
                 has_next_page = True
 
-        return PageInfo(has_previous_page=has_previous_page, has_next_page=has_next_page,
-                        start_cursor=start_cursor, end_cursor=end_cursor)
+        return PageInfo(
+            has_previous_page=has_previous_page,
+            has_next_page=has_next_page,
+            start_cursor=start_cursor,
+            end_cursor=end_cursor,
+        )
 
     def get_edge_cursor(self, num):
         return encode_cursor(self.slice_from + num)
diff --git a/openlobby/core/api/sanitizers.py b/openlobby/core/api/sanitizers.py
index 02245afc937c2a32e86fc70fa91e6f1dd01e80e4..9b741a5c9cdab2638a23657f4dda1e1a1dfec07c 100644
--- a/openlobby/core/api/sanitizers.py
+++ b/openlobby/core/api/sanitizers.py
@@ -8,4 +8,4 @@ def strip_all_tags(value):
 
 def extract_text(value):
     value = strip_all_tags(value)
-    return ' '.join(re.findall(r'(\b\w+)', value))
+    return " ".join(re.findall(r"(\b\w+)", value))
diff --git a/openlobby/core/api/schema.py b/openlobby/core/api/schema.py
index 9060e6ca465f24f7a8757dd0247cac4707374a2f..c2c79abf9e9b1e5355c750b08412067b37f70a37 100644
--- a/openlobby/core/api/schema.py
+++ b/openlobby/core/api/schema.py
@@ -12,12 +12,14 @@ from ..models import User, Report
 AUTHOR_SORT_LAST_NAME_ID = 1
 AUTHOR_SORT_TOTAL_REPORTS_ID = 2
 
+
 class AuthorSortEnum(graphene.Enum):
     LAST_NAME = AUTHOR_SORT_LAST_NAME_ID
     TOTAL_REPORTS = AUTHOR_SORT_TOTAL_REPORTS_ID
 
     class Meta:
-        description = 'Sort by field.'
+        description = "Sort by field."
+
 
 class AuthorsConnection(relay.Connection):
     total_count = graphene.Int()
@@ -34,36 +36,39 @@ class SearchReportsConnection(relay.Connection):
 
 
 def _get_authors_cache(ids):
-    authors = User.objects.filter(id__in=ids)\
-        .annotate(total_reports=Count('report', filter=Q(report__is_draft=False)))
+    authors = User.objects.filter(id__in=ids).annotate(
+        total_reports=Count("report", filter=Q(report__is_draft=False))
+    )
     return {a.id: types.Author.from_db(a) for a in authors}
 
 
 class Query:
-    highlight_help = ('Whether search matches should be marked with tag <mark>.'
-        ' Default: false')
+    highlight_help = (
+        "Whether search matches should be marked with tag <mark>." " Default: false"
+    )
 
     node = relay.Node.Field()
     authors = relay.ConnectionField(
         AuthorsConnection,
-        description='List of Authors. Returns first 10 nodes if pagination is not specified.',
+        description="List of Authors. Returns first 10 nodes if pagination is not specified.",
         sort=AuthorSortEnum(),
-        reversed=graphene.Boolean(default_value=False, description="Reverse order of sort")
+        reversed=graphene.Boolean(
+            default_value=False, description="Reverse order of sort"
+        ),
     )
     search_reports = relay.ConnectionField(
         SearchReportsConnection,
-        description='Fulltext search in Reports. Returns first 10 nodes if pagination is not specified.',
-        query=graphene.String(description='Text to search for.'),
+        description="Fulltext search in Reports. Returns first 10 nodes if pagination is not specified.",
+        query=graphene.String(description="Text to search for."),
         highlight=graphene.Boolean(default_value=False, description=highlight_help),
     )
-    viewer = graphene.Field(types.User, description='Active user viewing API.')
+    viewer = graphene.Field(types.User, description="Active user viewing API.")
     login_shortcuts = graphene.List(
         types.LoginShortcut,
-        description='Shortcuts for login. Use with LoginByShortcut mutation.',
+        description="Shortcuts for login. Use with LoginByShortcut mutation.",
     )
     report_drafts = graphene.List(
-        types.Report,
-        description='Saved drafts of reports for Viewer.',
+        types.Report, description="Saved drafts of reports for Viewer."
     )
 
     def resolve_authors(self, info, **kwargs):
@@ -71,9 +76,9 @@ class Query:
 
         total = User.objects.filter(is_author=True).count()
 
-        authors = User.objects\
-                      .sorted(**kwargs)\
-                      .filter(is_author=True)[paginator.slice_from:paginator.slice_to]
+        authors = User.objects.sorted(**kwargs).filter(is_author=True)[
+            paginator.slice_from : paginator.slice_to
+        ]
 
         page_info = paginator.get_page_info(total)
 
@@ -87,11 +92,9 @@ class Query:
 
     def resolve_search_reports(self, info, **kwargs):
         paginator = Paginator(**kwargs)
-        query = kwargs.get('query', '')
+        query = kwargs.get("query", "")
         query = extract_text(query)
-        params = {
-            'highlight': kwargs.get('highlight'),
-        }
+        params = {"highlight": kwargs.get("highlight")}
         response = search.query_reports(query, paginator, **params)
         total = response.hits.total
         page_info = paginator.get_page_info(total)
@@ -104,7 +107,9 @@ class Query:
                 node = types.Report.from_es(report, author=authors[report.author_id])
                 edges.append(SearchReportsConnection.Edge(node=node, cursor=cursor))
 
-        return SearchReportsConnection(page_info=page_info, edges=edges, total_count=total)
+        return SearchReportsConnection(
+            page_info=page_info, edges=edges, total_count=total
+        )
 
     def resolve_viewer(self, info, **kwargs):
         if info.context.user.is_authenticated:
@@ -113,7 +118,7 @@ class Query:
             return None
 
     def resolve_login_shortcuts(self, info, **kwargs):
-        clients = OpenIdClient.objects.filter(is_shortcut=True).order_by('name')
+        clients = OpenIdClient.objects.filter(is_shortcut=True).order_by("name")
         return [types.LoginShortcut.from_db(c) for c in clients]
 
     def resolve_report_drafts(self, info, **kwargs):
diff --git a/openlobby/core/api/types.py b/openlobby/core/api/types.py
index d552d370efe4c416bdd131363a719e72c35d0083..8d56829470f32fb7acc8eb75d898bdc9e18e029e 100644
--- a/openlobby/core/api/types.py
+++ b/openlobby/core/api/types.py
@@ -12,9 +12,9 @@ from .. import search
 
 def get_higlighted(hit, field):
     """Returns higlighted text of field if search is higlighted."""
-    if hasattr(hit.meta, 'highlight') and field in hit.meta.highlight:
+    if hasattr(hit.meta, "highlight") and field in hit.meta.highlight:
         return hit.meta.highlight[field][0]
-    return hit[field] if field in hit else ''
+    return hit[field] if field in hit else ""
 
 
 class Report(graphene.ObjectType):
@@ -31,7 +31,7 @@ class Report(graphene.ObjectType):
     extra = JSONString()
 
     class Meta:
-        interfaces = (relay.Node, )
+        interfaces = (relay.Node,)
 
     @classmethod
     def from_es(cls, report, author=None):
@@ -40,12 +40,12 @@ class Report(graphene.ObjectType):
             author=author,
             date=report.date,
             published=report.published,
-            title=get_higlighted(report, 'title'),
-            body=get_higlighted(report, 'body'),
-            received_benefit=get_higlighted(report, 'received_benefit'),
-            provided_benefit=get_higlighted(report, 'provided_benefit'),
-            our_participants=get_higlighted(report, 'our_participants'),
-            other_participants=get_higlighted(report, 'other_participants'),
+            title=get_higlighted(report, "title"),
+            body=get_higlighted(report, "body"),
+            received_benefit=get_higlighted(report, "received_benefit"),
+            provided_benefit=get_higlighted(report, "provided_benefit"),
+            our_participants=get_higlighted(report, "our_participants"),
+            other_participants=get_higlighted(report, "other_participants"),
             is_draft=report.is_draft,
             extra=report.extra,
         )
@@ -80,7 +80,7 @@ class Report(graphene.ObjectType):
             if report.author_id != info.context.user.id:
                 return None
 
-        author_type = cls._meta.fields['author'].type
+        author_type = cls._meta.fields["author"].type
         author = author_type.get_node(info, report.author_id)
         return cls.from_es(report, author)
 
@@ -102,7 +102,7 @@ class User(graphene.ObjectType):
     extra = JSONString()
 
     class Meta:
-        interfaces = (relay.Node, )
+        interfaces = (relay.Node,)
 
     @classmethod
     def from_db(cls, user):
@@ -135,7 +135,7 @@ class Author(graphene.ObjectType):
     reports = relay.ConnectionField(ReportConnection)
 
     class Meta:
-        interfaces = (relay.Node, )
+        interfaces = (relay.Node,)
 
     @classmethod
     def from_db(cls, user):
@@ -151,9 +151,9 @@ class Author(graphene.ObjectType):
     @classmethod
     def get_node(cls, info, id):
         try:
-            author = models.User.objects\
-                .annotate(total_reports=Count('report', filter=Q(report__is_draft=False)))\
-                .get(id=id, is_author=True)
+            author = models.User.objects.annotate(
+                total_reports=Count("report", filter=Q(report__is_draft=False))
+            ).get(id=id, is_author=True)
             return cls.from_db(author)
         except models.User.DoesNotExist:
             return None
@@ -180,7 +180,7 @@ class LoginShortcut(graphene.ObjectType):
     name = graphene.String()
 
     class Meta:
-        interfaces = (relay.Node, )
+        interfaces = (relay.Node,)
 
     @classmethod
     def from_db(cls, openid_client):
diff --git a/openlobby/core/api/utils.py b/openlobby/core/api/utils.py
index e2503c6f2b511527b797c270d6c758ecfbe2d7c7..8d6d7324fa8a0f9d03d8b181d9549b8e4eee3829 100644
--- a/openlobby/core/api/utils.py
+++ b/openlobby/core/api/utils.py
@@ -2,5 +2,5 @@ from django.http import JsonResponse
 
 
 def graphql_error_response(message, status_code=400):
-    error = {'message': message}
-    return JsonResponse({'errors': [error]}, status=status_code)
+    error = {"message": message}
+    return JsonResponse({"errors": [error]}, status=status_code)
diff --git a/openlobby/core/apps.py b/openlobby/core/apps.py
index 26f78a8e673340121f68a92930e2830bc58d269d..5ef1d600da3500626bfb855e8d489c82aeb6670f 100644
--- a/openlobby/core/apps.py
+++ b/openlobby/core/apps.py
@@ -2,4 +2,4 @@ from django.apps import AppConfig
 
 
 class CoreConfig(AppConfig):
-    name = 'core'
+    name = "core"
diff --git a/openlobby/core/auth.py b/openlobby/core/auth.py
index b49b3a94ef675e132f8df1e008812b8a6ba7b714..4508690585c4871ee48b8f5cf333f07dfe7968f3 100644
--- a/openlobby/core/auth.py
+++ b/openlobby/core/auth.py
@@ -6,14 +6,13 @@ import time
 def create_access_token(username, expiration=None):
     if expiration is None:
         expiration = int(time.time() + settings.SESSION_EXPIRATION)
-    payload = {
-        'sub': username,
-        'exp': expiration,
-    }
+    payload = {"sub": username, "exp": expiration}
     token = jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
-    return token.decode('utf-8')
+    return token.decode("utf-8")
 
 
 def parse_access_token(token):
-    payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
-    return payload['sub']
+    payload = jwt.decode(
+        token, settings.SECRET_KEY, algorithms=[settings.JWT_ALGORITHM]
+    )
+    return payload["sub"]
diff --git a/openlobby/core/documents.py b/openlobby/core/documents.py
index 69504a988e15884cf7774c618cc16cd41a597fe5..3923f6eada3d24fa47846899c2f07f7a2b665ba9 100644
--- a/openlobby/core/documents.py
+++ b/openlobby/core/documents.py
@@ -5,7 +5,7 @@ import json
 from .models import Report
 
 
-report = Index('{}-reports'.format(settings.ES_INDEX))
+report = Index("{}-reports".format(settings.ES_INDEX))
 
 
 @report.doc_type
@@ -30,8 +30,4 @@ class ReportDoc(DocType):
     class Meta:
         model = Report
 
-        fields = [
-            'date',
-            'published',
-            'is_draft',
-        ]
+        fields = ["date", "published", "is_draft"]
diff --git a/openlobby/core/middleware.py b/openlobby/core/middleware.py
index a6c1083c595d7ae6f7b7e0cba48a9561b455c8aa..a46c12324adb59364cf9dee35c19eb4a70ab3287 100644
--- a/openlobby/core/middleware.py
+++ b/openlobby/core/middleware.py
@@ -12,18 +12,20 @@ class TokenAuthMiddleware:
         self.get_response = get_response
 
     def __call__(self, request):
-        auth_header = request.META.get('HTTP_AUTHORIZATION')
+        auth_header = request.META.get("HTTP_AUTHORIZATION")
         if auth_header is not None:
-            m = re.match(r'Bearer (?P<token>.+)', auth_header)
+            m = re.match(r"Bearer (?P<token>.+)", auth_header)
             if m:
-                token = m.group('token')
+                token = m.group("token")
             else:
-                return graphql_error_response('Wrong Authorization header. Expected: "Bearer <token>"')
+                return graphql_error_response(
+                    'Wrong Authorization header. Expected: "Bearer <token>"'
+                )
 
             try:
                 username = parse_access_token(token)
             except Exception:
-                return graphql_error_response('Invalid Token.', 401)
+                return graphql_error_response("Invalid Token.", 401)
 
             try:
                 request.user = User.objects.get(username=username)
diff --git a/openlobby/core/migrations/0001_initial.py b/openlobby/core/migrations/0001_initial.py
index 6e16fd07305e7a325fdbe10617b20365eed5f2b3..530b306eec1c9186744c9e73b402ce6301d7ed4b 100644
--- a/openlobby/core/migrations/0001_initial.py
+++ b/openlobby/core/migrations/0001_initial.py
@@ -13,81 +13,203 @@ class Migration(migrations.Migration):
 
     initial = True
 
-    dependencies = [
-        ('auth', '0009_alter_user_last_name_max_length'),
-    ]
+    dependencies = [("auth", "0009_alter_user_last_name_max_length")]
 
     operations = [
         migrations.CreateModel(
-            name='User',
+            name="User",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('password', models.CharField(max_length=128, verbose_name='password')),
-                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
-                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
-                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
-                ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
-                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
-                ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
-                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
-                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
-                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
-                ('openid_uid', models.CharField(db_index=True, max_length=255, unique=True)),
-                ('extras', django.contrib.postgres.fields.jsonb.JSONField()),
-                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
-                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("password", models.CharField(max_length=128, verbose_name="password")),
+                (
+                    "last_login",
+                    models.DateTimeField(
+                        blank=True, null=True, verbose_name="last login"
+                    ),
+                ),
+                (
+                    "is_superuser",
+                    models.BooleanField(
+                        default=False,
+                        help_text="Designates that this user has all permissions without explicitly assigning them.",
+                        verbose_name="superuser status",
+                    ),
+                ),
+                (
+                    "username",
+                    models.CharField(
+                        error_messages={
+                            "unique": "A user with that username already exists."
+                        },
+                        help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
+                        max_length=150,
+                        unique=True,
+                        validators=[
+                            django.contrib.auth.validators.UnicodeUsernameValidator()
+                        ],
+                        verbose_name="username",
+                    ),
+                ),
+                (
+                    "first_name",
+                    models.CharField(
+                        blank=True, max_length=30, verbose_name="first name"
+                    ),
+                ),
+                (
+                    "last_name",
+                    models.CharField(
+                        blank=True, max_length=150, verbose_name="last name"
+                    ),
+                ),
+                (
+                    "email",
+                    models.EmailField(
+                        blank=True, max_length=254, verbose_name="email address"
+                    ),
+                ),
+                (
+                    "is_staff",
+                    models.BooleanField(
+                        default=False,
+                        help_text="Designates whether the user can log into this admin site.",
+                        verbose_name="staff status",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(
+                        default=True,
+                        help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
+                        verbose_name="active",
+                    ),
+                ),
+                (
+                    "date_joined",
+                    models.DateTimeField(
+                        default=django.utils.timezone.now, verbose_name="date joined"
+                    ),
+                ),
+                (
+                    "openid_uid",
+                    models.CharField(db_index=True, max_length=255, unique=True),
+                ),
+                ("extras", django.contrib.postgres.fields.jsonb.JSONField()),
+                (
+                    "groups",
+                    models.ManyToManyField(
+                        blank=True,
+                        help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
+                        related_name="user_set",
+                        related_query_name="user",
+                        to="auth.Group",
+                        verbose_name="groups",
+                    ),
+                ),
+                (
+                    "user_permissions",
+                    models.ManyToManyField(
+                        blank=True,
+                        help_text="Specific permissions for this user.",
+                        related_name="user_set",
+                        related_query_name="user",
+                        to="auth.Permission",
+                        verbose_name="user permissions",
+                    ),
+                ),
             ],
             options={
-                'verbose_name': 'user',
-                'verbose_name_plural': 'users',
-                'abstract': False,
+                "verbose_name": "user",
+                "verbose_name_plural": "users",
+                "abstract": False,
             },
-            managers=[
-                ('objects', django.contrib.auth.models.UserManager()),
-            ],
+            managers=[("objects", django.contrib.auth.models.UserManager())],
         ),
         migrations.CreateModel(
-            name='LoginAttempt',
+            name="LoginAttempt",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('state', models.CharField(db_index=True, max_length=50, unique=True)),
-                ('redirect_uri', models.CharField(max_length=255)),
-                ('expiration', models.IntegerField()),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("state", models.CharField(db_index=True, max_length=50, unique=True)),
+                ("redirect_uri", models.CharField(max_length=255)),
+                ("expiration", models.IntegerField()),
             ],
         ),
         migrations.CreateModel(
-            name='OpenIdClient',
+            name="OpenIdClient",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=255)),
-                ('is_shortcut', models.BooleanField(default=False)),
-                ('client_id', models.CharField(max_length=255)),
-                ('client_secret', models.CharField(max_length=255)),
-                ('issuer', models.CharField(db_index=True, max_length=255, unique=True)),
-                ('authorization_endpoint', models.CharField(max_length=255)),
-                ('token_endpoint', models.CharField(max_length=255)),
-                ('userinfo_endpoint', models.CharField(max_length=255)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=255)),
+                ("is_shortcut", models.BooleanField(default=False)),
+                ("client_id", models.CharField(max_length=255)),
+                ("client_secret", models.CharField(max_length=255)),
+                (
+                    "issuer",
+                    models.CharField(db_index=True, max_length=255, unique=True),
+                ),
+                ("authorization_endpoint", models.CharField(max_length=255)),
+                ("token_endpoint", models.CharField(max_length=255)),
+                ("userinfo_endpoint", models.CharField(max_length=255)),
             ],
         ),
         migrations.CreateModel(
-            name='Report',
+            name="Report",
             fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('date', models.DateTimeField()),
-                ('published', models.DateTimeField()),
-                ('title', models.TextField()),
-                ('body', models.TextField()),
-                ('received_benefit', models.TextField()),
-                ('provided_benefit', models.TextField()),
-                ('our_participants', models.TextField()),
-                ('other_participants', models.TextField()),
-                ('extra', django.contrib.postgres.fields.jsonb.JSONField()),
-                ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("date", models.DateTimeField()),
+                ("published", models.DateTimeField()),
+                ("title", models.TextField()),
+                ("body", models.TextField()),
+                ("received_benefit", models.TextField()),
+                ("provided_benefit", models.TextField()),
+                ("our_participants", models.TextField()),
+                ("other_participants", models.TextField()),
+                ("extra", django.contrib.postgres.fields.jsonb.JSONField()),
+                (
+                    "author",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.PROTECT,
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
             ],
         ),
         migrations.AddField(
-            model_name='loginattempt',
-            name='openid_client',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.OpenIdClient'),
+            model_name="loginattempt",
+            name="openid_client",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE, to="core.OpenIdClient"
+            ),
         ),
     ]
diff --git a/openlobby/core/migrations/0002_auto_20180116_2349.py b/openlobby/core/migrations/0002_auto_20180116_2349.py
index db82fcff43eea3210500cb4d4da010f13834d3fd..b3785e0270c3268c9937199e6cbe1707b163e3e3 100644
--- a/openlobby/core/migrations/0002_auto_20180116_2349.py
+++ b/openlobby/core/migrations/0002_auto_20180116_2349.py
@@ -6,44 +6,42 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
+    dependencies = [("core", "0001_initial")]
 
     operations = [
         migrations.AlterField(
-            model_name='report',
-            name='extra',
+            model_name="report",
+            name="extra",
             field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='report',
-            name='other_participants',
+            model_name="report",
+            name="other_participants",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='report',
-            name='our_participants',
+            model_name="report",
+            name="our_participants",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='report',
-            name='provided_benefit',
+            model_name="report",
+            name="provided_benefit",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='report',
-            name='received_benefit',
+            model_name="report",
+            name="received_benefit",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='report',
-            name='title',
+            model_name="report",
+            name="title",
             field=models.TextField(blank=True, null=True),
         ),
         migrations.AlterField(
-            model_name='user',
-            name='extras',
+            model_name="user",
+            name="extras",
             field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True),
         ),
     ]
diff --git a/openlobby/core/migrations/0003_auto_20180117_0030.py b/openlobby/core/migrations/0003_auto_20180117_0030.py
index b48c6ca7f0f47d8d7aabdf806ea40175902868fc..c0f55a23358cd58ff329451b09a03f777cb038d9 100644
--- a/openlobby/core/migrations/0003_auto_20180117_0030.py
+++ b/openlobby/core/migrations/0003_auto_20180117_0030.py
@@ -5,14 +5,8 @@ from django.db import migrations
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0002_auto_20180116_2349'),
-    ]
+    dependencies = [("core", "0002_auto_20180116_2349")]
 
     operations = [
-        migrations.RenameField(
-            model_name='user',
-            old_name='extras',
-            new_name='extra',
-        ),
+        migrations.RenameField(model_name="user", old_name="extras", new_name="extra")
     ]
diff --git a/openlobby/core/migrations/0004_user_is_author.py b/openlobby/core/migrations/0004_user_is_author.py
index 9a8e43e40003605a4240ef6fb5313ea118c8936d..0ba417286561e5f68f706eeb93953bb7bb21846e 100644
--- a/openlobby/core/migrations/0004_user_is_author.py
+++ b/openlobby/core/migrations/0004_user_is_author.py
@@ -5,14 +5,12 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0003_auto_20180117_0030'),
-    ]
+    dependencies = [("core", "0003_auto_20180117_0030")]
 
     operations = [
         migrations.AddField(
-            model_name='user',
-            name='is_author',
+            model_name="user",
+            name="is_author",
             field=models.BooleanField(default=False),
-        ),
+        )
     ]
diff --git a/openlobby/core/migrations/0005_auto_20180208_1210.py b/openlobby/core/migrations/0005_auto_20180208_1210.py
index ce3b8ec06ee7c9a645d3b12b0eec675870fbef0c..0b17bde07adc0033415235b8e20559ba3931d6e9 100644
--- a/openlobby/core/migrations/0005_auto_20180208_1210.py
+++ b/openlobby/core/migrations/0005_auto_20180208_1210.py
@@ -6,19 +6,17 @@ import django.utils.timezone
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0004_user_is_author'),
-    ]
+    dependencies = [("core", "0004_user_is_author")]
 
     operations = [
         migrations.RenameField(
-            model_name='loginattempt',
-            old_name='redirect_uri',
-            new_name='app_redirect_uri',
+            model_name="loginattempt",
+            old_name="redirect_uri",
+            new_name="app_redirect_uri",
         ),
         migrations.AlterField(
-            model_name='report',
-            name='published',
+            model_name="report",
+            name="published",
             field=models.DateTimeField(default=django.utils.timezone.now),
         ),
     ]
diff --git a/openlobby/core/migrations/0006_auto_20180208_1544.py b/openlobby/core/migrations/0006_auto_20180208_1544.py
index 90eb680791f7ec9859bce5fa141cc5c4d00b9387..b7298bb6ac55c93fd61dd7fde7b6af0787af7748 100644
--- a/openlobby/core/migrations/0006_auto_20180208_1544.py
+++ b/openlobby/core/migrations/0006_auto_20180208_1544.py
@@ -6,14 +6,14 @@ import openlobby.core.models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0005_auto_20180208_1210'),
-    ]
+    dependencies = [("core", "0005_auto_20180208_1210")]
 
     operations = [
         migrations.AlterField(
-            model_name='loginattempt',
-            name='expiration',
-            field=models.IntegerField(default=openlobby.core.models.get_login_attempt_expiration),
-        ),
+            model_name="loginattempt",
+            name="expiration",
+            field=models.IntegerField(
+                default=openlobby.core.models.get_login_attempt_expiration
+            ),
+        )
     ]
diff --git a/openlobby/core/migrations/0007_auto_20180209_1809.py b/openlobby/core/migrations/0007_auto_20180209_1809.py
index 898503bc22fcf9ae91e8e1198bcd8cdca320b1e3..ad0f2bb01e92071375ae0815f462df2d0b5fe115 100644
--- a/openlobby/core/migrations/0007_auto_20180209_1809.py
+++ b/openlobby/core/migrations/0007_auto_20180209_1809.py
@@ -5,21 +5,12 @@ from django.db import migrations
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0006_auto_20180208_1544'),
-    ]
+    dependencies = [("core", "0006_auto_20180208_1544")]
 
     operations = [
         migrations.RemoveField(
-            model_name='openidclient',
-            name='authorization_endpoint',
-        ),
-        migrations.RemoveField(
-            model_name='openidclient',
-            name='token_endpoint',
-        ),
-        migrations.RemoveField(
-            model_name='openidclient',
-            name='userinfo_endpoint',
+            model_name="openidclient", name="authorization_endpoint"
         ),
+        migrations.RemoveField(model_name="openidclient", name="token_endpoint"),
+        migrations.RemoveField(model_name="openidclient", name="userinfo_endpoint"),
     ]
diff --git a/openlobby/core/migrations/0008_loginattempt_openid_uid.py b/openlobby/core/migrations/0008_loginattempt_openid_uid.py
index 7243cf4b4e815bbdfe72527bc2c56de8a9abb51e..986697dbe940ad544311a8e79646752d2853ac1d 100644
--- a/openlobby/core/migrations/0008_loginattempt_openid_uid.py
+++ b/openlobby/core/migrations/0008_loginattempt_openid_uid.py
@@ -5,14 +5,12 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0007_auto_20180209_1809'),
-    ]
+    dependencies = [("core", "0007_auto_20180209_1809")]
 
     operations = [
         migrations.AddField(
-            model_name='loginattempt',
-            name='openid_uid',
+            model_name="loginattempt",
+            name="openid_uid",
             field=models.CharField(max_length=255, null=True),
-        ),
+        )
     ]
diff --git a/openlobby/core/migrations/0009_auto_20180217_1850.py b/openlobby/core/migrations/0009_auto_20180217_1850.py
index 88afb4af1cd95ba957cdc1d231bbe994378c5fce..716785d2471d150c92fd6c1a059259de097bdc06 100644
--- a/openlobby/core/migrations/0009_auto_20180217_1850.py
+++ b/openlobby/core/migrations/0009_auto_20180217_1850.py
@@ -5,14 +5,12 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0008_loginattempt_openid_uid'),
-    ]
+    dependencies = [("core", "0008_loginattempt_openid_uid")]
 
     operations = [
         migrations.AlterField(
-            model_name='user',
-            name='openid_uid',
+            model_name="user",
+            name="openid_uid",
             field=models.CharField(max_length=255, null=True),
-        ),
+        )
     ]
diff --git a/openlobby/core/migrations/0010_user_has_colliding_name.py b/openlobby/core/migrations/0010_user_has_colliding_name.py
index 5eae315ff2b9d87c1231b044675ca91c7611794d..220e2b3f6328b33d1ff0a70063e1d1845785fa62 100644
--- a/openlobby/core/migrations/0010_user_has_colliding_name.py
+++ b/openlobby/core/migrations/0010_user_has_colliding_name.py
@@ -5,14 +5,12 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0009_auto_20180217_1850'),
-    ]
+    dependencies = [("core", "0009_auto_20180217_1850")]
 
     operations = [
         migrations.AddField(
-            model_name='user',
-            name='has_colliding_name',
+            model_name="user",
+            name="has_colliding_name",
             field=models.BooleanField(default=False),
-        ),
+        )
     ]
diff --git a/openlobby/core/migrations/0011_report_is_draft.py b/openlobby/core/migrations/0011_report_is_draft.py
index f5a7d1865998efdb4c5a051196217a7b6acd6aed..a7ef9d9fb8bbbfa7ef4c1b2f81a04b9822ff27df 100644
--- a/openlobby/core/migrations/0011_report_is_draft.py
+++ b/openlobby/core/migrations/0011_report_is_draft.py
@@ -5,14 +5,12 @@ from django.db import migrations, models
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('core', '0010_user_has_colliding_name'),
-    ]
+    dependencies = [("core", "0010_user_has_colliding_name")]
 
     operations = [
         migrations.AddField(
-            model_name='report',
-            name='is_draft',
+            model_name="report",
+            name="is_draft",
             field=models.BooleanField(default=False),
-        ),
+        )
     ]
diff --git a/openlobby/core/models.py b/openlobby/core/models.py
index 8c46ec0e6455123c6318a998e037bd34e0888686..adb32d601b1d36628d2414d6d7fa465e180fecbf 100644
--- a/openlobby/core/models.py
+++ b/openlobby/core/models.py
@@ -13,13 +13,25 @@ from django.utils import timezone
 class UserManager(BaseUserManager):
     def sorted(self, **kwargs):
         # inline import intentionally
-        from openlobby.core.api.schema import AUTHOR_SORT_LAST_NAME_ID, AUTHOR_SORT_TOTAL_REPORTS_ID
-        qs = self.get_queryset().annotate(total_reports=Count('report', filter=Q(report__is_draft=False)))
-        sort_field = kwargs.get('sort', AUTHOR_SORT_LAST_NAME_ID)
+        from openlobby.core.api.schema import (
+            AUTHOR_SORT_LAST_NAME_ID,
+            AUTHOR_SORT_TOTAL_REPORTS_ID,
+        )
+
+        qs = self.get_queryset().annotate(
+            total_reports=Count("report", filter=Q(report__is_draft=False))
+        )
+        sort_field = kwargs.get("sort", AUTHOR_SORT_LAST_NAME_ID)
         if sort_field == AUTHOR_SORT_LAST_NAME_ID:
-            return qs.order_by('{}last_name'.format('-' if kwargs.get('reversed', False) else ''), 'first_name')
+            return qs.order_by(
+                "{}last_name".format("-" if kwargs.get("reversed", False) else ""),
+                "first_name",
+            )
         elif sort_field == AUTHOR_SORT_TOTAL_REPORTS_ID:
-            return qs.order_by('{}total_reports'.format('' if kwargs.get('reversed', False) else '-'), 'last_name')
+            return qs.order_by(
+                "{}total_reports".format("" if kwargs.get("reversed", False) else "-"),
+                "last_name",
+            )
         raise NotImplemented("Other sort types are not implemented")
 
 
@@ -27,6 +39,7 @@ class User(AbstractUser):
     """Custom user model. For simplicity we store OpenID 'sub' identifier in
     username field.
     """
+
     openid_uid = models.CharField(max_length=255, null=True)
     extra = JSONField(null=True, blank=True)
     is_author = models.BooleanField(default=False)
@@ -36,8 +49,9 @@ class User(AbstractUser):
     def save(self, *args, **kwargs):
         # deal with first name and last name collisions
         if self.is_author:
-            collisions = User.objects.filter(first_name=self.first_name, last_name=self.last_name,
-                                             is_author=True).exclude(id=self.id)
+            collisions = User.objects.filter(
+                first_name=self.first_name, last_name=self.last_name, is_author=True
+            ).exclude(id=self.id)
             if collisions.count() > 0:
                 self.has_colliding_name = True
                 collisions.update(has_colliding_name=True)
@@ -48,6 +62,7 @@ class OpenIdClient(models.Model):
     """Stores connection parameters for OpenID Clients. Some may be used as
     login shortcuts.
     """
+
     name = models.CharField(max_length=255)
     is_shortcut = models.BooleanField(default=False)
     client_id = models.CharField(max_length=255)
@@ -64,6 +79,7 @@ def get_login_attempt_expiration():
 
 class LoginAttempt(models.Model):
     """Temporary login attempt details which persists redirects."""
+
     openid_client = models.ForeignKey(OpenIdClient, on_delete=models.CASCADE)
     state = models.CharField(max_length=50, unique=True, db_index=True)
     app_redirect_uri = models.CharField(max_length=255)
diff --git a/openlobby/core/openid.py b/openlobby/core/openid.py
index 0ce9422a7cf012cd702d9178fd95cd7114d8a2aa..88b8d28e81d3bcc2432cf9f4fba2778ef95c55d5 100644
--- a/openlobby/core/openid.py
+++ b/openlobby/core/openid.py
@@ -17,9 +17,9 @@ def discover_issuer(openid_uid):
 def init_client_for_shortcut(openid_client_obj):
     client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
     reg_info = {
-        'client_id': openid_client_obj.client_id,
-        'client_secret': openid_client_obj.client_secret,
-        'redirect_uris': [settings.REDIRECT_URI],
+        "client_id": openid_client_obj.client_id,
+        "client_secret": openid_client_obj.client_secret,
+        "redirect_uris": [settings.REDIRECT_URI],
     }
     client_reg = RegistrationResponse(**reg_info)
     client.store_registration_info(client_reg)
@@ -31,37 +31,40 @@ def register_client(issuer):
     client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
     client.provider_config(issuer)
     params = {
-        'redirect_uris': [settings.REDIRECT_URI],
-        'client_name': settings.SITE_NAME,
+        "redirect_uris": [settings.REDIRECT_URI],
+        "client_name": settings.SITE_NAME,
     }
-    client.register(client.provider_info['registration_endpoint'], **params)
+    client.register(client.provider_info["registration_endpoint"], **params)
     return client
 
 
 def get_authorization_url(client, state):
     args = {
-        'client_id': client.client_id,
-        'response_type': 'code',
-        'scope': 'openid',
-        'state': state,
-        'redirect_uri': client.registration_response['redirect_uris'][0],
-        'claims': ClaimsRequest(userinfo=Claims(
-            given_name={'essential': True},
-            family_name={'essential': True},
-            email={'essential': True},
-        )),
+        "client_id": client.client_id,
+        "response_type": "code",
+        "scope": "openid",
+        "state": state,
+        "redirect_uri": client.registration_response["redirect_uris"][0],
+        "claims": ClaimsRequest(
+            userinfo=Claims(
+                given_name={"essential": True},
+                family_name={"essential": True},
+                email={"essential": True},
+            )
+        ),
     }
 
     auth_req = client.construct_AuthorizationRequest(request_args=args)
-    return auth_req.request(client.provider_info['authorization_endpoint'])
+    return auth_req.request(client.provider_info["authorization_endpoint"])
 
 
 def get_user_info(client, query_string):
     """Processes query string from OpenID redirect and returns user info."""
-    aresp = client.parse_response(AuthorizationResponse, info=query_string,
-        sformat='urlencoded')
+    aresp = client.parse_response(
+        AuthorizationResponse, info=query_string, sformat="urlencoded"
+    )
 
-    args = {'code': aresp['code'], 'redirect_uri': settings.REDIRECT_URI}
-    client.do_access_token_request(state=aresp['state'], request_args=args)
+    args = {"code": aresp["code"], "redirect_uri": settings.REDIRECT_URI}
+    client.do_access_token_request(state=aresp["state"], request_args=args)
 
-    return client.do_user_info_request(state=aresp['state'])
+    return client.do_user_info_request(state=aresp["state"])
diff --git a/openlobby/core/search.py b/openlobby/core/search.py
index a87e167207b887f227aa4f175ac67ed5b163f7fe..fcf4bd2d7d0f5b2b862941d13625a1774779819b 100644
--- a/openlobby/core/search.py
+++ b/openlobby/core/search.py
@@ -2,30 +2,36 @@ from .documents import ReportDoc
 
 
 HIGHLIGHT_PARAMS = {
-    'number_of_fragments': 0,
-    'pre_tags': ['<mark>'],
-    'post_tags': ['</mark>'],
+    "number_of_fragments": 0,
+    "pre_tags": ["<mark>"],
+    "post_tags": ["</mark>"],
 }
 
 
 def query_reports(query, paginator, *, highlight=False):
-    fields = ['title', 'body', 'received_benefit', 'provided_benefit',
-        'our_participants', 'other_participants']
+    fields = [
+        "title",
+        "body",
+        "received_benefit",
+        "provided_benefit",
+        "our_participants",
+        "other_participants",
+    ]
     s = ReportDoc.search()
-    s = s.exclude('term', is_draft=True)
-    if query != '':
-        s = s.query('multi_match', query=query, fields=fields)
+    s = s.exclude("term", is_draft=True)
+    if query != "":
+        s = s.query("multi_match", query=query, fields=fields)
     if highlight:
         s = s.highlight(*fields, **HIGHLIGHT_PARAMS)
-    s = s.sort('-date')
-    s = s[paginator.slice_from:paginator.slice_to]
+    s = s.sort("-date")
+    s = s[paginator.slice_from : paginator.slice_to]
     return s.execute()
 
 
 def reports_by_author(author_id, paginator):
     s = ReportDoc.search()
-    s = s.exclude('term', is_draft=True)
-    s = s.filter('term', author_id=author_id)
-    s = s.sort('-date')
-    s = s[paginator.slice_from:paginator.slice_to]
+    s = s.exclude("term", is_draft=True)
+    s = s.filter("term", author_id=author_id)
+    s = s.sort("-date")
+    s = s[paginator.slice_from : paginator.slice_to]
     return s.execute()
diff --git a/openlobby/core/views.py b/openlobby/core/views.py
index e3780e971f20d6352f5229a46d89196a2e840360..0a2b79e4768cfdd1f7396c7f5cfd5c926c6fcafc 100644
--- a/openlobby/core/views.py
+++ b/openlobby/core/views.py
@@ -6,25 +6,22 @@ import urllib.parse
 
 from .auth import create_access_token
 from .models import LoginAttempt, User
-from .openid import (
-    init_client_for_shortcut,
-    get_user_info,
-)
+from .openid import init_client_for_shortcut, get_user_info
 
 
 class IndexView(TemplateView):
-    template_name = 'core/index.html'
+    template_name = "core/index.html"
 
 
 class LoginRedirectView(View):
 
     # TODO redirect to app_redirect_uri on fail
     def get(self, request, **kwargs):
-        query_string = request.META['QUERY_STRING']
+        query_string = request.META["QUERY_STRING"]
 
         # get login attempt
-        state = request.GET.get('state')
-        la = LoginAttempt.objects.select_related('openid_client').get(state=state)
+        state = request.GET.get("state")
+        la = LoginAttempt.objects.select_related("openid_client").get(state=state)
         app_redirect_uri = la.app_redirect_uri
 
         if la.expiration < time.time():
@@ -38,14 +35,17 @@ class LoginRedirectView(View):
         client = init_client_for_shortcut(la.openid_client)
         user_info = get_user_info(client, query_string)
 
-        user, created = User.objects.get_or_create(username=user_info['sub'], defaults={
-            'username': user_info['sub'],
-            'first_name': user_info['given_name'],
-            'last_name': user_info['family_name'],
-            'email': user_info['email'],
-            'openid_uid': la.openid_uid,
-        })
+        user, created = User.objects.get_or_create(
+            username=user_info["sub"],
+            defaults={
+                "username": user_info["sub"],
+                "first_name": user_info["given_name"],
+                "last_name": user_info["family_name"],
+                "email": user_info["email"],
+                "openid_uid": la.openid_uid,
+            },
+        )
 
         token = create_access_token(user.username)
-        token_qs = urllib.parse.urlencode({'token': token})
-        return redirect('{}?{}'.format(app_redirect_uri, token_qs))
+        token_qs = urllib.parse.urlencode({"token": token})
+        return redirect("{}?{}".format(app_redirect_uri, token_qs))
diff --git a/openlobby/schema.py b/openlobby/schema.py
index 5772e2fd8a448384edf4b427c50b69aaa3c3ca41..4e5a6359cfacbb4fa085fef77e9af0ec8408afa8 100644
--- a/openlobby/schema.py
+++ b/openlobby/schema.py
@@ -13,5 +13,6 @@ class Mutation(CoreMutation, graphene.ObjectType):
     pass
 
 
-schema = graphene.Schema(query=Query, mutation=Mutation,
-    types=[Author, User, Report, LoginShortcut])
+schema = graphene.Schema(
+    query=Query, mutation=Mutation, types=[Author, User, Report, LoginShortcut]
+)
diff --git a/openlobby/settings.py b/openlobby/settings.py
index 034304d16162f9f4521bef39f031da6570ebc8dc..7fcb0b24cda95d0b4ba11212bb99a8676bf2d729 100644
--- a/openlobby/settings.py
+++ b/openlobby/settings.py
@@ -5,107 +5,106 @@ import dsnparse
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = 'DEBUG' in os.environ
+DEBUG = "DEBUG" in os.environ
 
 # SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = os.environ.get('SECRET_KEY')
+SECRET_KEY = os.environ.get("SECRET_KEY")
 if not SECRET_KEY:
     if DEBUG:
-        SECRET_KEY = 'not-secret-at-all'
+        SECRET_KEY = "not-secret-at-all"
     else:
-        raise RuntimeError('Missing SECRET_KEY environment variable.')
+        raise RuntimeError("Missing SECRET_KEY environment variable.")
 
-ALLOWED_HOSTS = ['*']
+ALLOWED_HOSTS = ["*"]
 
 
 # Application definition
 
 INSTALLED_APPS = [
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.staticfiles',
-    'django_extensions',
-    'graphene_django',
-    'django_elasticsearch_dsl',
-    'openlobby.core',
+    "django.contrib.admin",
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.staticfiles",
+    "django_extensions",
+    "graphene_django",
+    "django_elasticsearch_dsl",
+    "openlobby.core",
 ]
 
 MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'openlobby.core.middleware.TokenAuthMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
+    "django.middleware.security.SecurityMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "django.middleware.common.CommonMiddleware",
+    "django.middleware.csrf.CsrfViewMiddleware",
+    "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "openlobby.core.middleware.TokenAuthMiddleware",
+    "django.middleware.clickjacking.XFrameOptionsMiddleware",
+    "django.contrib.messages.middleware.MessageMiddleware",
 ]
 
-ROOT_URLCONF = 'openlobby.urls'
+ROOT_URLCONF = "openlobby.urls"
 
 TEMPLATES = [
     {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
-            ],
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            "context_processors": [
+                "django.template.context_processors.debug",
+                "django.template.context_processors.request",
+                "django.contrib.auth.context_processors.auth",
+                "django.contrib.messages.context_processors.messages",
+            ]
         },
-    },
+    }
 ]
 
-WSGI_APPLICATION = 'openlobby.wsgi.application'
+WSGI_APPLICATION = "openlobby.wsgi.application"
 
-AUTH_USER_MODEL = 'core.User'
+AUTH_USER_MODEL = "core.User"
 
-DATABASE_DSN = os.environ.get('DATABASE_DSN', 'postgresql://db:db@localhost:5432/openlobby')
+DATABASE_DSN = os.environ.get(
+    "DATABASE_DSN", "postgresql://db:db@localhost:5432/openlobby"
+)
 db = dsnparse.parse(DATABASE_DSN)
-assert db.scheme == 'postgresql'
+assert db.scheme == "postgresql"
 
 DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.postgresql',
-        'NAME': db.paths[0],
-        'USER': db.username,
-        'PASSWORD': db.password,
-        'HOST': db.host,
-        'PORT': db.port,
+    "default": {
+        "ENGINE": "django.db.backends.postgresql",
+        "NAME": db.paths[0],
+        "USER": db.username,
+        "PASSWORD": db.password,
+        "HOST": db.host,
+        "PORT": db.port,
     }
 }
 
 ELASTICSEARCH_DSL = {
-    'default': {
-        'hosts': os.environ.get('ELASTICSEARCH_DSN', 'http://localhost:9200'),
-    },
+    "default": {"hosts": os.environ.get("ELASTICSEARCH_DSN", "http://localhost:9200")}
 }
 
-ELASTICSEARCH_DSL_INDEX_SETTINGS = {
-    'number_of_shards': 1,
-    'number_of_replicas': 0,
-}
+ELASTICSEARCH_DSL_INDEX_SETTINGS = {"number_of_shards": 1, "number_of_replicas": 0}
 
 # Password validation
 
 AUTH_PASSWORD_VALIDATORS = [
-    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
-    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
-    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
-    {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
+    {
+        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
+    },
+    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
+    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
+    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
 ]
 
 
 # Internationalization
 
-LANGUAGE_CODE = 'cs'
+LANGUAGE_CODE = "cs"
 
-TIME_ZONE = 'Europe/Prague'
+TIME_ZONE = "Europe/Prague"
 
 USE_I18N = True
 
@@ -114,40 +113,31 @@ USE_L10N = True
 USE_TZ = True
 
 
-STATIC_ROOT = os.path.join(BASE_DIR, 'static')
-STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(BASE_DIR, "static")
+STATIC_URL = "/static/"
 
 LOGGING = {
-    'version': 1,
-    'handlers': {
-        'console': {
-            'class': 'logging.StreamHandler',
-        },
-    },
-    'loggers': {
-        'django': {
-            'handlers': ['console'],
-            'level': 'INFO' if DEBUG else 'WARNING',
-        },
+    "version": 1,
+    "handlers": {"console": {"class": "logging.StreamHandler"}},
+    "loggers": {
+        "django": {"handlers": ["console"], "level": "INFO" if DEBUG else "WARNING"}
     },
 }
 
 
-GRAPHENE = {
-    'SCHEMA': 'openlobby.schema.schema'
-}
+GRAPHENE = {"SCHEMA": "openlobby.schema.schema"}
 
 ###############################################################################
 # Custom settings
 
 # Elasticsearch index with reports
-ES_INDEX = os.environ.get('ES_INDEX', 'openlobby')
+ES_INDEX = os.environ.get("ES_INDEX", "openlobby")
 
 # default analyzer for text fields
-ES_TEXT_ANALYZER = os.environ.get('ES_TEXT_ANALYZER', 'czech')
+ES_TEXT_ANALYZER = os.environ.get("ES_TEXT_ANALYZER", "czech")
 
 # signature algorithm JSON Web Tokens
-JWT_ALGORITHM = 'HS512'
+JWT_ALGORITHM = "HS512"
 
 # expiration time (seconds) of login attempt
 LOGIN_ATTEMPT_EXPIRATION = 300
@@ -156,7 +146,7 @@ LOGIN_ATTEMPT_EXPIRATION = 300
 SESSION_EXPIRATION = 60 * 60 * 24 * 14
 
 # name of the site used in OpenID authentication
-SITE_NAME = os.environ.get('SITE_NAME', 'Open Lobby')
+SITE_NAME = os.environ.get("SITE_NAME", "Open Lobby")
 
 # redirect URI used in OpenID authentication
-REDIRECT_URI = os.environ.get('REDIRECT_URI', 'http://localhost:8010/login-redirect')
+REDIRECT_URI = os.environ.get("REDIRECT_URI", "http://localhost:8010/login-redirect")
diff --git a/openlobby/urls.py b/openlobby/urls.py
index f9f5fed53ee512e7cc1ad4eeb090775ac5d0f9e3..76c329216daebcda53b4f34724550fda823c528f 100644
--- a/openlobby/urls.py
+++ b/openlobby/urls.py
@@ -6,8 +6,8 @@ from graphene_django.views import GraphQLView
 from openlobby.core.views import IndexView, LoginRedirectView
 
 urlpatterns = [
-    path('', IndexView.as_view(), name='index'),
-    path('login-redirect', LoginRedirectView.as_view(), name='login-redirect'),
-    path('admin/', admin.site.urls),
-    path('graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),
+    path("", IndexView.as_view(), name="index"),
+    path("login-redirect", LoginRedirectView.as_view(), name="login-redirect"),
+    path("admin/", admin.site.urls),
+    path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))),
 ]
diff --git a/setup.py b/setup.py
index 3477bf9b938c9110a1cb28c3a4470906c24c1e28..e367ab68bdc967db1a78ff81a4197ed1b8a0478c 100644
--- a/setup.py
+++ b/setup.py
@@ -6,37 +6,32 @@ from os import path
 here = path.abspath(path.dirname(__file__))
 
 # Get the long description from the README file
-with open(path.join(here, 'README.md'), encoding='utf-8') as f:
+with open(path.join(here, "README.md"), encoding="utf-8") as f:
     long_description = f.read()
 
 
 setup(
-    name='openlobby',
-    version='0.1.0',
-    url='https://github.com/openlobby/openlobby-server',
-
-    author='Jan Bednarik',
-    author_email='jan.bednarik@gmail.com',
-
-    description='Open Lobby Server',
+    name="openlobby",
+    version="0.1.0",
+    url="https://github.com/openlobby/openlobby-server",
+    author="Jan Bednarik",
+    author_email="jan.bednarik@gmail.com",
+    description="Open Lobby Server",
     long_description=long_description,
-
-    packages=find_packages(exclude=['tests']),
-
+    packages=find_packages(exclude=["tests"]),
     # TODO
     # install_requires=[],
     # extras_require={
     #     'dev': [],
     #     'test': [],
     # },
-
-    license='MIT',
+    license="MIT",
     classifiers=[
-        'Development Status :: 4 - Beta',
-        'License :: OSI Approved :: MIT License',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
+        "Development Status :: 4 - Beta",
+        "License :: OSI Approved :: MIT License",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
+        "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
     ],
 )
diff --git a/tests/conftest.py b/tests/conftest.py
index 6d9cc6b844b8a82264ff793dfe73c4f31c7593b7..9b345233e1b1a2feb570ce62dff7951625706bbd 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -24,14 +24,17 @@ def django_es():
 
 
 def pytest_addoption(parser):
-    parser.addoption('--issuer', action='store',
-        help='OpenID Provider (server) issuer URL. Provider must allow client registration.')
+    parser.addoption(
+        "--issuer",
+        action="store",
+        help="OpenID Provider (server) issuer URL. Provider must allow client registration.",
+    )
 
 
-@pytest.fixture(scope='session')
+@pytest.fixture(scope="session")
 def issuer(request):
     """OpenID Provider issuer URL."""
-    url = request.config.getoption('--issuer')
+    url = request.config.getoption("--issuer")
     if url is None:
-        pytest.skip('Missing OpenID Provider URL.')
+        pytest.skip("Missing OpenID Provider URL.")
     return url
diff --git a/tests/dummy.py b/tests/dummy.py
index 5e99de33667e8857523805e188bb7749fa0960c7..3cbe43ddf384bafd6b6d0608e3643decc34c6b0a 100644
--- a/tests/dummy.py
+++ b/tests/dummy.py
@@ -5,87 +5,87 @@ from openlobby.core.models import Report, User
 
 authors = [
     {
-        'id': 1,
-        'username': 'wolf',
-        'first_name': 'Winston',
-        'last_name': 'Wolfe',
-        'is_author': True,
-        'extra': {'movies': 1},
+        "id": 1,
+        "username": "wolf",
+        "first_name": "Winston",
+        "last_name": "Wolfe",
+        "is_author": True,
+        "extra": {"movies": 1},
     },
     {
-        'id': 2,
-        'username': 'sponge',
-        'first_name': 'Spongebob',
-        'last_name': 'Squarepants',
-        'is_author': True,
+        "id": 2,
+        "username": "sponge",
+        "first_name": "Spongebob",
+        "last_name": "Squarepants",
+        "is_author": True,
     },
     {
-        'id': 3,
-        'username': 'shaun',
-        'first_name': 'Shaun',
-        'last_name': 'Sheep',
-        'is_author': True,
+        "id": 3,
+        "username": "shaun",
+        "first_name": "Shaun",
+        "last_name": "Sheep",
+        "is_author": True,
     },
 ]
 
 reports = [
     {
-        'id': 1,
-        'date': arrow.get(2018, 1, 1).datetime,
-        'published': arrow.get(2018, 1, 2).datetime,
-        'title': 'The Fellowship of the Ring',
-        'body': 'Long story short: we got the Ring!',
-        'received_benefit': 'The Ring',
-        'provided_benefit': '',
-        'our_participants': 'Frodo, Gandalf',
-        'other_participants': 'Saruman',
+        "id": 1,
+        "date": arrow.get(2018, 1, 1).datetime,
+        "published": arrow.get(2018, 1, 2).datetime,
+        "title": "The Fellowship of the Ring",
+        "body": "Long story short: we got the Ring!",
+        "received_benefit": "The Ring",
+        "provided_benefit": "",
+        "our_participants": "Frodo, Gandalf",
+        "other_participants": "Saruman",
     },
     {
-        'id': 2,
-        'date': arrow.get(2018, 1, 3).datetime,
-        'published': arrow.get(2018, 1, 4).datetime,
-        'title': 'The Two Towers',
-        'body': 'Another long story.',
-        'received_benefit': 'Mithrill Jacket',
-        'provided_benefit': '',
-        'our_participants': 'Frodo, Gimli, Legolas',
-        'other_participants': 'Saruman, Sauron',
-        'extra': {'rings': 1},
+        "id": 2,
+        "date": arrow.get(2018, 1, 3).datetime,
+        "published": arrow.get(2018, 1, 4).datetime,
+        "title": "The Two Towers",
+        "body": "Another long story.",
+        "received_benefit": "Mithrill Jacket",
+        "provided_benefit": "",
+        "our_participants": "Frodo, Gimli, Legolas",
+        "other_participants": "Saruman, Sauron",
+        "extra": {"rings": 1},
     },
     {
-        'id': 3,
-        'date': arrow.get(2018, 1, 5).datetime,
-        'published': arrow.get(2018, 1, 6).datetime,
-        'title': 'The Return of the King',
-        'body': 'Aragorn is the King. And we have lost the Ring.',
-        'received_benefit': '',
-        'provided_benefit': 'The Ring',
-        'our_participants': 'Aragorn',
-        'other_participants': 'Sauron',
+        "id": 3,
+        "date": arrow.get(2018, 1, 5).datetime,
+        "published": arrow.get(2018, 1, 6).datetime,
+        "title": "The Return of the King",
+        "body": "Aragorn is the King. And we have lost the Ring.",
+        "received_benefit": "",
+        "provided_benefit": "The Ring",
+        "our_participants": "Aragorn",
+        "other_participants": "Sauron",
     },
     {
-        'id': 4,
-        'date': arrow.get(2018, 1, 7).datetime,
-        'published': arrow.get(2018, 1, 8).datetime,
-        'title': 'The Silmarillion',
-        'body': 'Not finished yet.',
-        'received_benefit': '',
-        'provided_benefit': '',
-        'our_participants': '',
-        'other_participants': '',
-        'is_draft': True,
+        "id": 4,
+        "date": arrow.get(2018, 1, 7).datetime,
+        "published": arrow.get(2018, 1, 8).datetime,
+        "title": "The Silmarillion",
+        "body": "Not finished yet.",
+        "received_benefit": "",
+        "provided_benefit": "",
+        "our_participants": "",
+        "other_participants": "",
+        "is_draft": True,
     },
     {
-        'id': 5,
-        'date': arrow.get(2018, 1, 9).datetime,
-        'published': arrow.get(2018, 1, 10).datetime,
-        'title': 'The Hobbit',
-        'body': 'Work in progress...',
-        'received_benefit': '',
-        'provided_benefit': '',
-        'our_participants': '',
-        'other_participants': '',
-        'is_draft': True,
+        "id": 5,
+        "date": arrow.get(2018, 1, 9).datetime,
+        "published": arrow.get(2018, 1, 10).datetime,
+        "title": "The Hobbit",
+        "body": "Work in progress...",
+        "received_benefit": "",
+        "provided_benefit": "",
+        "our_participants": "",
+        "other_participants": "",
+        "is_draft": True,
     },
 ]
 
diff --git a/tests/mutations/snapshots/snap_test_create_report.py b/tests/mutations/snapshots/snap_test_create_report.py
index 4b33904c5e744101dc6a1f08549d614de449d9fa..b4abeb0b329c49c5aa6161b549a8f8a18179e392 100644
--- a/tests/mutations/snapshots/snap_test_create_report.py
+++ b/tests/mutations/snapshots/snap_test_create_report.py
@@ -7,72 +7,65 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_unauthorized 1'] = {
-    'data': {
-        'createReport': None
-    },
-    'errors': [
+snapshots["test_unauthorized 1"] = {
+    "data": {"createReport": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 5,
-                    'line': 3
-                }
-            ],
-            'message': 'User must be logged in to perform this mutation.'
+            "locations": [{"column": 5, "line": 3}],
+            "message": "User must be logged in to perform this mutation.",
         }
-    ]
+    ],
 }
 
-snapshots['test_full_report 1'] = {
-    'data': {
-        'createReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 1
+snapshots["test_full_report 1"] = {
+    "data": {
+        "createReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 1,
                 },
-                'body': 'I visited Tesla factory and talked with Elon Musk.',
-                'date': '2018-01-01 00:00:00+00:00',
-                'extra': None,
-                'id': '__STRIPPED__',
-                'isDraft': False,
-                'otherParticipants': 'Elon Musk',
-                'ourParticipants': 'me',
-                'providedBenefit': 'nothing',
-                'published': '__STRIPPED__',
-                'receivedBenefit': 'Tesla Model S',
-                'title': 'Free Tesla'
+                "body": "I visited Tesla factory and talked with Elon Musk.",
+                "date": "2018-01-01 00:00:00+00:00",
+                "extra": None,
+                "id": "__STRIPPED__",
+                "isDraft": False,
+                "otherParticipants": "Elon Musk",
+                "ourParticipants": "me",
+                "providedBenefit": "nothing",
+                "published": "__STRIPPED__",
+                "receivedBenefit": "Tesla Model S",
+                "title": "Free Tesla",
             }
         }
     }
 }
 
-snapshots['test_is_draft 1'] = {
-    'data': {
-        'createReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 0
+snapshots["test_is_draft 1"] = {
+    "data": {
+        "createReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 0,
                 },
-                'body': 'Niel deGrasse Tyson just visited me...',
-                'date': '2018-01-03 00:00:00+00:00',
-                'extra': None,
-                'id': '__STRIPPED__',
-                'isDraft': True,
-                'otherParticipants': 'Neil deGrasse Tyson',
-                'ourParticipants': 'myself',
-                'providedBenefit': 'coffee',
-                'published': '__STRIPPED__',
-                'receivedBenefit': 'touch of the God',
-                'title': 'Visited by old friend'
+                "body": "Niel deGrasse Tyson just visited me...",
+                "date": "2018-01-03 00:00:00+00:00",
+                "extra": None,
+                "id": "__STRIPPED__",
+                "isDraft": True,
+                "otherParticipants": "Neil deGrasse Tyson",
+                "ourParticipants": "myself",
+                "providedBenefit": "coffee",
+                "published": "__STRIPPED__",
+                "receivedBenefit": "touch of the God",
+                "title": "Visited by old friend",
             }
         }
     }
diff --git a/tests/mutations/snapshots/snap_test_login.py b/tests/mutations/snapshots/snap_test_login.py
index 8a36af706ac9e7d00be5361a9589e8636245927c..8d93fa0e325843ede1fc3b87d874152fad9c6bfc 100644
--- a/tests/mutations/snapshots/snap_test_login.py
+++ b/tests/mutations/snapshots/snap_test_login.py
@@ -7,30 +7,18 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_login__known_openid_client 1'] = {
-    'userinfo': {
-        'email': {
-            'essential': True
-        },
-        'family_name': {
-            'essential': True
-        },
-        'given_name': {
-            'essential': True
-        }
+snapshots["test_login__known_openid_client 1"] = {
+    "userinfo": {
+        "email": {"essential": True},
+        "family_name": {"essential": True},
+        "given_name": {"essential": True},
     }
 }
 
-snapshots['test_login__new_openid_client 1'] = {
-    'userinfo': {
-        'email': {
-            'essential': True
-        },
-        'family_name': {
-            'essential': True
-        },
-        'given_name': {
-            'essential': True
-        }
+snapshots["test_login__new_openid_client 1"] = {
+    "userinfo": {
+        "email": {"essential": True},
+        "family_name": {"essential": True},
+        "given_name": {"essential": True},
     }
 }
diff --git a/tests/mutations/snapshots/snap_test_login_by_shortcut.py b/tests/mutations/snapshots/snap_test_login_by_shortcut.py
index 6fe834f111a4cd7b14863c5eb635217f3b69679a..4e57bd374cfcfff52edf05b4c4ec984b306a6d6f 100644
--- a/tests/mutations/snapshots/snap_test_login_by_shortcut.py
+++ b/tests/mutations/snapshots/snap_test_login_by_shortcut.py
@@ -7,16 +7,10 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_login_by_shortcut 1'] = {
-    'userinfo': {
-        'email': {
-            'essential': True
-        },
-        'family_name': {
-            'essential': True
-        },
-        'given_name': {
-            'essential': True
-        }
+snapshots["test_login_by_shortcut 1"] = {
+    "userinfo": {
+        "email": {"essential": True},
+        "family_name": {"essential": True},
+        "given_name": {"essential": True},
     }
 }
diff --git a/tests/mutations/snapshots/snap_test_update_report.py b/tests/mutations/snapshots/snap_test_update_report.py
index b2c4902c0e51f1abea3494e1ca8fd970ab63baad..64eab571f7052579e2372e3e9451e2602149124e 100644
--- a/tests/mutations/snapshots/snap_test_update_report.py
+++ b/tests/mutations/snapshots/snap_test_update_report.py
@@ -7,177 +7,149 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_unauthorized 1'] = {
-    'data': {
-        'updateReport': None
-    },
-    'errors': [
+snapshots["test_unauthorized 1"] = {
+    "data": {"updateReport": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 5,
-                    'line': 3
-                }
-            ],
-            'message': 'User must be logged in to perform this mutation.'
+            "locations": [{"column": 5, "line": 3}],
+            "message": "User must be logged in to perform this mutation.",
         }
-    ]
+    ],
 }
 
-snapshots['test_not_author 1'] = {
-    'data': {
-        'updateReport': None
-    },
-    'errors': [
+snapshots["test_not_author 1"] = {
+    "data": {"updateReport": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 5,
-                    'line': 3
-                }
-            ],
-            'message': 'Viewer is not the Author of this Report or Report does not exist.'
+            "locations": [{"column": 5, "line": 3}],
+            "message": "Viewer is not the Author of this Report or Report does not exist.",
         }
-    ]
+    ],
 }
 
-snapshots['test_report_does_not_exist 1'] = {
-    'data': {
-        'updateReport': None
-    },
-    'errors': [
+snapshots["test_report_does_not_exist 1"] = {
+    "data": {"updateReport": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 5,
-                    'line': 3
-                }
-            ],
-            'message': 'Viewer is not the Author of this Report or Report does not exist.'
+            "locations": [{"column": 5, "line": 3}],
+            "message": "Viewer is not the Author of this Report or Report does not exist.",
         }
-    ]
+    ],
 }
 
-snapshots['test_update_published_with_draft 1'] = {
-    'data': {
-        'updateReport': None
-    },
-    'errors': [
+snapshots["test_update_published_with_draft 1"] = {
+    "data": {"updateReport": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 5,
-                    'line': 3
-                }
-            ],
-            'message': 'You cannot update published Report with draft.'
+            "locations": [{"column": 5, "line": 3}],
+            "message": "You cannot update published Report with draft.",
         }
-    ]
+    ],
 }
 
-snapshots['test_update_draft_with_draft 1'] = {
-    'data': {
-        'updateReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 0
+snapshots["test_update_draft_with_draft 1"] = {
+    "data": {
+        "updateReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 0,
                 },
-                'body': 'I visited Tesla factory and talked with Elon Musk.',
-                'date': '2018-03-03 00:00:00+00:00',
-                'extra': None,
-                'id': 'UmVwb3J0OjE=',
-                'isDraft': True,
-                'otherParticipants': 'Elon Musk',
-                'ourParticipants': 'me',
-                'providedBenefit': 'nothing',
-                'published': '2018-03-08 00:00:00+00:00',
-                'receivedBenefit': 'Tesla Model S',
-                'title': 'Free Tesla'
+                "body": "I visited Tesla factory and talked with Elon Musk.",
+                "date": "2018-03-03 00:00:00+00:00",
+                "extra": None,
+                "id": "UmVwb3J0OjE=",
+                "isDraft": True,
+                "otherParticipants": "Elon Musk",
+                "ourParticipants": "me",
+                "providedBenefit": "nothing",
+                "published": "2018-03-08 00:00:00+00:00",
+                "receivedBenefit": "Tesla Model S",
+                "title": "Free Tesla",
             }
         }
     }
 }
 
-snapshots['test_update_draft_with_published 1'] = {
-    'data': {
-        'updateReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 1
+snapshots["test_update_draft_with_published 1"] = {
+    "data": {
+        "updateReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 1,
                 },
-                'body': 'I visited Tesla factory and talked with Elon Musk.',
-                'date': '2018-03-03 00:00:00+00:00',
-                'extra': None,
-                'id': 'UmVwb3J0OjE=',
-                'isDraft': False,
-                'otherParticipants': 'Elon Musk',
-                'ourParticipants': 'me',
-                'providedBenefit': 'nothing',
-                'published': '2018-03-08 00:00:00+00:00',
-                'receivedBenefit': 'Tesla Model S',
-                'title': 'Free Tesla'
+                "body": "I visited Tesla factory and talked with Elon Musk.",
+                "date": "2018-03-03 00:00:00+00:00",
+                "extra": None,
+                "id": "UmVwb3J0OjE=",
+                "isDraft": False,
+                "otherParticipants": "Elon Musk",
+                "ourParticipants": "me",
+                "providedBenefit": "nothing",
+                "published": "2018-03-08 00:00:00+00:00",
+                "receivedBenefit": "Tesla Model S",
+                "title": "Free Tesla",
             }
         }
     }
 }
 
-snapshots['test_update_published_with_published 1'] = {
-    'data': {
-        'updateReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 1
+snapshots["test_update_published_with_published 1"] = {
+    "data": {
+        "updateReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 1,
                 },
-                'body': 'I visited Tesla factory and talked with Elon Musk.',
-                'date': '2018-03-03 00:00:00+00:00',
-                'extra': None,
-                'id': 'UmVwb3J0OjE=',
-                'isDraft': False,
-                'otherParticipants': 'Elon Musk',
-                'ourParticipants': 'me',
-                'providedBenefit': 'nothing',
-                'published': '2018-03-08 00:00:00+00:00',
-                'receivedBenefit': 'Tesla Model S',
-                'title': 'Free Tesla'
+                "body": "I visited Tesla factory and talked with Elon Musk.",
+                "date": "2018-03-03 00:00:00+00:00",
+                "extra": None,
+                "id": "UmVwb3J0OjE=",
+                "isDraft": False,
+                "otherParticipants": "Elon Musk",
+                "ourParticipants": "me",
+                "providedBenefit": "nothing",
+                "published": "2018-03-08 00:00:00+00:00",
+                "receivedBenefit": "Tesla Model S",
+                "title": "Free Tesla",
             }
         }
     }
 }
 
-snapshots['test_input_sanitization 1'] = {
-    'data': {
-        'updateReport': {
-            'report': {
-                'author': {
-                    'extra': '{"movies": 1}',
-                    'firstName': 'Winston',
-                    'id': 'QXV0aG9yOjE=',
-                    'lastName': 'Wolfe',
-                    'totalReports': 1
+snapshots["test_input_sanitization 1"] = {
+    "data": {
+        "updateReport": {
+            "report": {
+                "author": {
+                    "extra": '{"movies": 1}',
+                    "firstName": "Winston",
+                    "id": "QXV0aG9yOjE=",
+                    "lastName": "Wolfe",
+                    "totalReports": 1,
                 },
-                'body': 'some link in body',
-                'date': '2018-03-03 00:00:00+00:00',
-                'extra': None,
-                'id': 'UmVwb3J0OjE=',
-                'isDraft': False,
-                'otherParticipants': 'you!',
-                'ourParticipants': 'me, myself',
-                'providedBenefit': 'tea',
-                'published': '2018-03-08 00:00:00+00:00',
-                'receivedBenefit': 'coffee',
-                'title': 'No tags'
+                "body": "some link in body",
+                "date": "2018-03-03 00:00:00+00:00",
+                "extra": None,
+                "id": "UmVwb3J0OjE=",
+                "isDraft": False,
+                "otherParticipants": "you!",
+                "ourParticipants": "me, myself",
+                "providedBenefit": "tea",
+                "published": "2018-03-08 00:00:00+00:00",
+                "receivedBenefit": "coffee",
+                "title": "No tags",
             }
         }
     }
diff --git a/tests/mutations/test_create_report.py b/tests/mutations/test_create_report.py
index df1837c42062434088bd8cd6c250b9b6c8122d11..32ccbf90394a1c05e66806d422645a046dd2b13e 100644
--- a/tests/mutations/test_create_report.py
+++ b/tests/mutations/test_create_report.py
@@ -8,7 +8,7 @@ from ..dummy import prepare_author
 from ..utils import call_api, strip_value
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 query = """
@@ -46,9 +46,9 @@ def setup():
 
 def test_unauthorized(client, snapshot):
     input = {
-        'title': 'Short Story',
-        'body': 'I told you!',
-        'date': arrow.utcnow().isoformat(),
+        "title": "Short Story",
+        "body": "I told you!",
+        "date": arrow.utcnow().isoformat(),
     }
     response = call_api(client, query, input)
     snapshot.assert_match(response)
@@ -56,28 +56,28 @@ def test_unauthorized(client, snapshot):
 
 def test_full_report(client, snapshot):
     date = arrow.get(2018, 1, 1)
-    title = 'Free Tesla'
-    body = 'I visited Tesla factory and talked with Elon Musk.'
-    received_benefit = 'Tesla Model S'
-    provided_benefit = 'nothing'
-    our_participants = 'me'
-    other_participants = 'Elon Musk'
+    title = "Free Tesla"
+    body = "I visited Tesla factory and talked with Elon Musk."
+    received_benefit = "Tesla Model S"
+    provided_benefit = "nothing"
+    our_participants = "me"
+    other_participants = "Elon Musk"
     input = {
-        'title': title,
-        'body': body,
-        'receivedBenefit': received_benefit,
-        'providedBenefit': provided_benefit,
-        'ourParticipants': our_participants,
-        'otherParticipants': other_participants,
-        'date': date.isoformat(),
+        "title": title,
+        "body": body,
+        "receivedBenefit": received_benefit,
+        "providedBenefit": provided_benefit,
+        "ourParticipants": our_participants,
+        "otherParticipants": other_participants,
+        "date": date.isoformat(),
     }
 
-    response = call_api(client, query, input, 'wolf')
+    response = call_api(client, query, input, "wolf")
 
-    published = strip_value(response, 'data', 'createReport', 'report', 'published')
+    published = strip_value(response, "data", "createReport", "report", "published")
 
-    id = strip_value(response, 'data', 'createReport', 'report', 'id')
-    assert re.match(r'\w+', id)
+    id = strip_value(response, "data", "createReport", "report", "id")
+    assert re.match(r"\w+", id)
 
     snapshot.assert_match(response)
 
@@ -97,51 +97,51 @@ def test_full_report(client, snapshot):
 
 def test_input_sanitization(client):
     input = {
-        'title': '<s>No</s> tags',
-        'body': 'some <a href="http://foo">link</a> <br>in body',
-        'receivedBenefit': '<b>coffee</b>',
-        'providedBenefit': '<li>tea',
-        'ourParticipants': 'me, <u>myself</u>',
-        'otherParticipants': '<strong>you!</strong>',
-        'date': arrow.utcnow().isoformat(),
+        "title": "<s>No</s> tags",
+        "body": 'some <a href="http://foo">link</a> <br>in body',
+        "receivedBenefit": "<b>coffee</b>",
+        "providedBenefit": "<li>tea",
+        "ourParticipants": "me, <u>myself</u>",
+        "otherParticipants": "<strong>you!</strong>",
+        "date": arrow.utcnow().isoformat(),
     }
 
-    call_api(client, query, input, 'wolf')
+    call_api(client, query, input, "wolf")
 
     report = Report.objects.get()
-    assert report.title == 'No tags'
-    assert report.body == 'some link in body'
-    assert report.received_benefit == 'coffee'
-    assert report.provided_benefit == 'tea'
-    assert report.our_participants == 'me, myself'
-    assert report.other_participants == 'you!'
+    assert report.title == "No tags"
+    assert report.body == "some link in body"
+    assert report.received_benefit == "coffee"
+    assert report.provided_benefit == "tea"
+    assert report.our_participants == "me, myself"
+    assert report.other_participants == "you!"
 
 
 def test_is_draft(client, snapshot):
     date = arrow.get(2018, 1, 3)
-    title = 'Visited by old friend'
-    body = 'Niel deGrasse Tyson just visited me...'
-    received_benefit = 'touch of the God'
-    provided_benefit = 'coffee'
-    our_participants = 'myself'
-    other_participants = 'Neil deGrasse Tyson'
+    title = "Visited by old friend"
+    body = "Niel deGrasse Tyson just visited me..."
+    received_benefit = "touch of the God"
+    provided_benefit = "coffee"
+    our_participants = "myself"
+    other_participants = "Neil deGrasse Tyson"
     input = {
-        'title': title,
-        'body': body,
-        'receivedBenefit': received_benefit,
-        'providedBenefit': provided_benefit,
-        'ourParticipants': our_participants,
-        'otherParticipants': other_participants,
-        'date': date.isoformat(),
-        'isDraft': True,
+        "title": title,
+        "body": body,
+        "receivedBenefit": received_benefit,
+        "providedBenefit": provided_benefit,
+        "ourParticipants": our_participants,
+        "otherParticipants": other_participants,
+        "date": date.isoformat(),
+        "isDraft": True,
     }
 
-    response = call_api(client, query, input, 'wolf')
+    response = call_api(client, query, input, "wolf")
 
-    published = strip_value(response, 'data', 'createReport', 'report', 'published')
+    published = strip_value(response, "data", "createReport", "report", "published")
 
-    id = strip_value(response, 'data', 'createReport', 'report', 'id')
-    assert re.match(r'\w+', id)
+    id = strip_value(response, "data", "createReport", "report", "id")
+    assert re.match(r"\w+", id)
 
     snapshot.assert_match(response)
 
diff --git a/tests/mutations/test_login.py b/tests/mutations/test_login.py
index 4ea608c5ec2b6808a4b5365d86fba6c81902bd88..fb6f6bc300d91890115daf237c57bdd1436ac503 100644
--- a/tests/mutations/test_login.py
+++ b/tests/mutations/test_login.py
@@ -15,39 +15,49 @@ pytestmark = pytest.mark.django_db
 
 def check_authorization_url(authorization_url, oid_client, state, snapshot):
     url = urlparse(authorization_url)
-    url_without_query = urlunparse((url.scheme, url.netloc, url.path, '', '', ''))
-    assert url_without_query == '{}/protocol/openid-connect/auth'.format(oid_client.issuer)
+    url_without_query = urlunparse((url.scheme, url.netloc, url.path, "", "", ""))
+    assert url_without_query == "{}/protocol/openid-connect/auth".format(
+        oid_client.issuer
+    )
 
     qs = parse_qs(url.query)
-    assert qs['client_id'][0] == oid_client.client_id
-    assert qs['response_type'][0] == 'code'
-    assert qs['scope'][0] == 'openid'
-    assert qs['redirect_uri'][0] == 'http://localhost:8010/login-redirect'
-    assert qs['state'][0] == state
-    snapshot.assert_match(json.loads(qs['claims'][0]))
+    assert qs["client_id"][0] == oid_client.client_id
+    assert qs["response_type"][0] == "code"
+    assert qs["scope"][0] == "openid"
+    assert qs["redirect_uri"][0] == "http://localhost:8010/login-redirect"
+    assert qs["state"][0] == state
+    snapshot.assert_match(json.loads(qs["claims"][0]))
 
 
 def test_login__known_openid_client(issuer, client, snapshot):
     oc = register_client(issuer)
-    oid_client = OpenIdClient.objects.create(name='Test', issuer=issuer,
-        client_id=oc.client_id, client_secret=oc.client_secret)
-
-    app_redirect_uri = 'http://i.am.pirate'
-    openid_uid = 'wolf@openid.provider'
+    oid_client = OpenIdClient.objects.create(
+        name="Test",
+        issuer=issuer,
+        client_id=oc.client_id,
+        client_secret=oc.client_secret,
+    )
+
+    app_redirect_uri = "http://i.am.pirate"
+    openid_uid = "wolf@openid.provider"
     query = """
     mutation {{
         login (input: {{ openidUid: "{uid}", redirectUri: "{uri}" }}) {{
             authorizationUrl
         }}
     }}
-    """.format(uid=openid_uid, uri=app_redirect_uri)
+    """.format(
+        uid=openid_uid, uri=app_redirect_uri
+    )
     # Keycloak server used for tests does not support issuer discovery by UID, so we mock it
-    with patch('openlobby.core.api.mutations.discover_issuer', return_value=issuer) as mock:
+    with patch(
+        "openlobby.core.api.mutations.discover_issuer", return_value=issuer
+    ) as mock:
         response = call_api(client, query)
         mock.assert_called_once_with(openid_uid)
 
-    assert 'errors' not in response
-    authorization_url = response['data']['login']['authorizationUrl']
+    assert "errors" not in response
+    authorization_url = response["data"]["login"]["authorizationUrl"]
 
     la = LoginAttempt.objects.get(openid_client__id=oid_client.id)
     assert la.app_redirect_uri == app_redirect_uri
@@ -57,28 +67,32 @@ def test_login__known_openid_client(issuer, client, snapshot):
 
 
 def test_login__new_openid_client(issuer, client, snapshot):
-    app_redirect_uri = 'http://i.am.pirate'
-    openid_uid = 'wolf@openid.provider'
+    app_redirect_uri = "http://i.am.pirate"
+    openid_uid = "wolf@openid.provider"
     query = """
     mutation {{
         login (input: {{ openidUid: "{uid}", redirectUri: "{uri}" }}) {{
             authorizationUrl
         }}
     }}
-    """.format(uid=openid_uid, uri=app_redirect_uri)
+    """.format(
+        uid=openid_uid, uri=app_redirect_uri
+    )
     # Keycloak server used for tests does not support issuer discovery by UID, so we mock it
-    with patch('openlobby.core.api.mutations.discover_issuer', return_value=issuer) as mock:
+    with patch(
+        "openlobby.core.api.mutations.discover_issuer", return_value=issuer
+    ) as mock:
         response = call_api(client, query)
         mock.assert_called_once_with(openid_uid)
 
-    assert 'errors' not in response
-    authorization_url = response['data']['login']['authorizationUrl']
+    assert "errors" not in response
+    authorization_url = response["data"]["login"]["authorizationUrl"]
 
     oid_client = OpenIdClient.objects.get()
     assert oid_client.name == issuer
     assert oid_client.issuer == issuer
-    assert re.match(r'\w+', oid_client.client_id)
-    assert re.match(r'\w+', oid_client.client_secret)
+    assert re.match(r"\w+", oid_client.client_id)
+    assert re.match(r"\w+", oid_client.client_secret)
 
     la = LoginAttempt.objects.get(openid_client__id=oid_client.id)
     assert la.app_redirect_uri == app_redirect_uri
diff --git a/tests/mutations/test_login_by_shortcut.py b/tests/mutations/test_login_by_shortcut.py
index 8e9dee4acf9df7481b36fc01e5f4871478db5519..6238aa2952fa5e85cf4bc43c0d290a5e8f29d356 100644
--- a/tests/mutations/test_login_by_shortcut.py
+++ b/tests/mutations/test_login_by_shortcut.py
@@ -12,21 +12,28 @@ pytestmark = pytest.mark.django_db
 
 def test_login_by_shortcut(issuer, client, snapshot):
     oc = register_client(issuer)
-    oid_client = OpenIdClient.objects.create(name='Test', is_shortcut=True,
-        issuer=issuer, client_id=oc.client_id, client_secret=oc.client_secret)
-
-    app_redirect_uri = 'http://i.am.pirate'
+    oid_client = OpenIdClient.objects.create(
+        name="Test",
+        is_shortcut=True,
+        issuer=issuer,
+        client_id=oc.client_id,
+        client_secret=oc.client_secret,
+    )
+
+    app_redirect_uri = "http://i.am.pirate"
     query = """
     mutation {{
         loginByShortcut (input: {{ shortcutId: "{id}", redirectUri: "{uri}" }}) {{
             authorizationUrl
         }}
     }}
-    """.format(id=to_global_id('LoginShortcut', oid_client.id), uri=app_redirect_uri)
+    """.format(
+        id=to_global_id("LoginShortcut", oid_client.id), uri=app_redirect_uri
+    )
     response = call_api(client, query)
 
-    assert 'errors' not in response
-    authorization_url = response['data']['loginByShortcut']['authorizationUrl']
+    assert "errors" not in response
+    authorization_url = response["data"]["loginByShortcut"]["authorizationUrl"]
 
     la = LoginAttempt.objects.get(openid_client__id=oid_client.id)
     assert la.app_redirect_uri == app_redirect_uri
diff --git a/tests/mutations/test_update_report.py b/tests/mutations/test_update_report.py
index 94e9267b0e9f6942d4e9cc8a0898afa3644216d7..3486c5ba59aed8df1d666ed701447342870a09fc 100644
--- a/tests/mutations/test_update_report.py
+++ b/tests/mutations/test_update_report.py
@@ -9,7 +9,7 @@ from ..dummy import prepare_report
 from ..utils import call_api
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 query = """
@@ -42,25 +42,25 @@ mutation updateReport ($input: UpdateReportInput!) {
 published = arrow.get(2018, 3, 8)
 
 date = arrow.get(2018, 3, 3)
-title = 'Free Tesla'
-body = 'I visited Tesla factory and talked with Elon Musk.'
-received_benefit = 'Tesla Model S'
-provided_benefit = 'nothing'
-our_participants = 'me'
-other_participants = 'Elon Musk'
+title = "Free Tesla"
+body = "I visited Tesla factory and talked with Elon Musk."
+received_benefit = "Tesla Model S"
+provided_benefit = "nothing"
+our_participants = "me"
+other_participants = "Elon Musk"
 
 
 def get_input(is_draft=False, id=1):
     return {
-        'id': to_global_id('Report', id),
-        'title': title,
-        'body': body,
-        'receivedBenefit': received_benefit,
-        'providedBenefit': provided_benefit,
-        'ourParticipants': our_participants,
-        'otherParticipants': other_participants,
-        'date': date.isoformat(),
-        'isDraft': is_draft,
+        "id": to_global_id("Report", id),
+        "title": title,
+        "body": body,
+        "receivedBenefit": received_benefit,
+        "providedBenefit": provided_benefit,
+        "ourParticipants": our_participants,
+        "otherParticipants": other_participants,
+        "date": date.isoformat(),
+        "isDraft": is_draft,
     }
 
 
@@ -88,31 +88,31 @@ def test_unauthorized(client, snapshot):
 
 def test_not_author(client, snapshot):
     prepare_report()
-    User.objects.create(id=2, username='hacker')
+    User.objects.create(id=2, username="hacker")
     input = get_input()
-    response = call_api(client, query, input, 'hacker')
+    response = call_api(client, query, input, "hacker")
     snapshot.assert_match(response)
 
 
 def test_report_does_not_exist(client, snapshot):
     prepare_report()
     input = get_input(id=666)
-    response = call_api(client, query, input, 'wolf')
+    response = call_api(client, query, input, "wolf")
     snapshot.assert_match(response)
 
 
 def test_update_published_with_draft(client, snapshot):
     prepare_report()
     input = get_input(is_draft=True)
-    response = call_api(client, query, input, 'wolf')
+    response = call_api(client, query, input, "wolf")
     snapshot.assert_match(response)
 
 
 def test_update_draft_with_draft(client, snapshot):
     prepare_report(is_draft=True)
     input = get_input(is_draft=True)
-    with patch('openlobby.core.api.mutations.arrow.utcnow', return_value=published):
-        response = call_api(client, query, input, 'wolf')
+    with patch("openlobby.core.api.mutations.arrow.utcnow", return_value=published):
+        response = call_api(client, query, input, "wolf")
     snapshot.assert_match(response)
     assert_report(is_draft=True)
 
@@ -120,8 +120,8 @@ def test_update_draft_with_draft(client, snapshot):
 def test_update_draft_with_published(client, snapshot):
     prepare_report(is_draft=True)
     input = get_input()
-    with patch('openlobby.core.api.mutations.arrow.utcnow', return_value=published):
-        response = call_api(client, query, input, 'wolf')
+    with patch("openlobby.core.api.mutations.arrow.utcnow", return_value=published):
+        response = call_api(client, query, input, "wolf")
     snapshot.assert_match(response)
     assert_report()
 
@@ -129,8 +129,8 @@ def test_update_draft_with_published(client, snapshot):
 def test_update_published_with_published(client, snapshot):
     prepare_report()
     input = get_input()
-    with patch('openlobby.core.api.mutations.arrow.utcnow', return_value=published):
-        response = call_api(client, query, input, 'wolf')
+    with patch("openlobby.core.api.mutations.arrow.utcnow", return_value=published):
+        response = call_api(client, query, input, "wolf")
     snapshot.assert_match(response)
     assert_report()
 
@@ -138,25 +138,25 @@ def test_update_published_with_published(client, snapshot):
 def test_input_sanitization(client, snapshot):
     prepare_report()
     input = {
-        'id': to_global_id('Report', 1),
-        'title': '<s>No</s> tags',
-        'body': 'some <a href="http://foo">link</a> <br>in body',
-        'receivedBenefit': '<b>coffee</b>',
-        'providedBenefit': '<li>tea',
-        'ourParticipants': 'me, <u>myself</u>',
-        'otherParticipants': '<strong>you!</strong>',
-        'date': date.isoformat(),
+        "id": to_global_id("Report", 1),
+        "title": "<s>No</s> tags",
+        "body": 'some <a href="http://foo">link</a> <br>in body',
+        "receivedBenefit": "<b>coffee</b>",
+        "providedBenefit": "<li>tea",
+        "ourParticipants": "me, <u>myself</u>",
+        "otherParticipants": "<strong>you!</strong>",
+        "date": date.isoformat(),
     }
 
-    with patch('openlobby.core.api.mutations.arrow.utcnow', return_value=published):
-        response = call_api(client, query, input, 'wolf')
+    with patch("openlobby.core.api.mutations.arrow.utcnow", return_value=published):
+        response = call_api(client, query, input, "wolf")
 
     snapshot.assert_match(response)
 
     report = Report.objects.get()
-    assert report.title == 'No tags'
-    assert report.body == 'some link in body'
-    assert report.received_benefit == 'coffee'
-    assert report.provided_benefit == 'tea'
-    assert report.our_participants == 'me, myself'
-    assert report.other_participants == 'you!'
+    assert report.title == "No tags"
+    assert report.body == "some link in body"
+    assert report.received_benefit == "coffee"
+    assert report.provided_benefit == "tea"
+    assert report.our_participants == "me, myself"
+    assert report.other_participants == "you!"
diff --git a/tests/schema/snapshots/snap_test_authors.py b/tests/schema/snapshots/snap_test_authors.py
index cf9fba0e09487210dbca4670b052d2d65f9c3fd3..fee760ed81195b6f8e693ca922b91ef1eb1a7e38 100644
--- a/tests/schema/snapshots/snap_test_authors.py
+++ b/tests/schema/snapshots/snap_test_authors.py
@@ -7,507 +7,496 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_all 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_all 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_first 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_first 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
-                }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mg==',
-                'hasNextPage': True,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mg==",
+                "hasNextPage": True,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_first_after 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_first_after 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 }
             ],
-            'pageInfo': {
-                'endCursor': 'Mg==',
-                'hasNextPage': True,
-                'hasPreviousPage': True,
-                'startCursor': 'Mg=='
+            "pageInfo": {
+                "endCursor": "Mg==",
+                "hasNextPage": True,
+                "hasPreviousPage": True,
+                "startCursor": "Mg==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_last 1'] = {
-    'data': {
-        'authors': None
-    },
-    'errors': [
+snapshots["test_last 1"] = {
+    "data": {"authors": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 9,
-                    'line': 3
-                }
-            ],
-            'message': 'Pagination "last" works only in combination with "before" argument.'
+            "locations": [{"column": 9, "line": 3}],
+            "message": 'Pagination "last" works only in combination with "before" argument.',
         }
-    ]
+    ],
 }
 
-snapshots['test_last_before 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_last_before 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 }
             ],
-            'pageInfo': {
-                'endCursor': 'Mg==',
-                'hasNextPage': True,
-                'hasPreviousPage': True,
-                'startCursor': 'Mg=='
+            "pageInfo": {
+                "endCursor": "Mg==",
+                "hasNextPage": True,
+                "hasPreviousPage": True,
+                "startCursor": "Mg==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_with_reports 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_with_reports 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'reports': {
-                            'edges': [
-                            ],
-                            'totalCount': 0
-                        },
-                        'totalReports': 0
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "reports": {"edges": [], "totalCount": 0},
+                        "totalReports": 0,
                     }
                 },
                 {
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'reports': {
-                            'edges': [
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "reports": {
+                            "edges": [
                                 {
-                                    'cursor': 'MQ==',
-                                    'node': {
-                                        'body': 'Another long story.',
-                                        'date': '2018-01-03 00:00:00+00:00',
-                                        'extra': '{"rings": 1}',
-                                        'id': 'UmVwb3J0OjI=',
-                                        'isDraft': False,
-                                        'otherParticipants': 'Saruman, Sauron',
-                                        'ourParticipants': 'Frodo, Gimli, Legolas',
-                                        'providedBenefit': '',
-                                        'published': '2018-01-04 00:00:00+00:00',
-                                        'receivedBenefit': 'Mithrill Jacket',
-                                        'title': 'The Two Towers'
-                                    }
+                                    "cursor": "MQ==",
+                                    "node": {
+                                        "body": "Another long story.",
+                                        "date": "2018-01-03 00:00:00+00:00",
+                                        "extra": '{"rings": 1}',
+                                        "id": "UmVwb3J0OjI=",
+                                        "isDraft": False,
+                                        "otherParticipants": "Saruman, Sauron",
+                                        "ourParticipants": "Frodo, Gimli, Legolas",
+                                        "providedBenefit": "",
+                                        "published": "2018-01-04 00:00:00+00:00",
+                                        "receivedBenefit": "Mithrill Jacket",
+                                        "title": "The Two Towers",
+                                    },
                                 }
                             ],
-                            'totalCount': 1
+                            "totalCount": 1,
                         },
-                        'totalReports': 1
+                        "totalReports": 1,
                     }
                 },
                 {
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'reports': {
-                            'edges': [
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "reports": {
+                            "edges": [
                                 {
-                                    'cursor': 'MQ==',
-                                    'node': {
-                                        'body': 'Aragorn is the King. And we have lost the Ring.',
-                                        'date': '2018-01-05 00:00:00+00:00',
-                                        'extra': None,
-                                        'id': 'UmVwb3J0OjM=',
-                                        'isDraft': False,
-                                        'otherParticipants': 'Sauron',
-                                        'ourParticipants': 'Aragorn',
-                                        'providedBenefit': 'The Ring',
-                                        'published': '2018-01-06 00:00:00+00:00',
-                                        'receivedBenefit': '',
-                                        'title': 'The Return of the King'
-                                    }
+                                    "cursor": "MQ==",
+                                    "node": {
+                                        "body": "Aragorn is the King. And we have lost the Ring.",
+                                        "date": "2018-01-05 00:00:00+00:00",
+                                        "extra": None,
+                                        "id": "UmVwb3J0OjM=",
+                                        "isDraft": False,
+                                        "otherParticipants": "Sauron",
+                                        "ourParticipants": "Aragorn",
+                                        "providedBenefit": "The Ring",
+                                        "published": "2018-01-06 00:00:00+00:00",
+                                        "receivedBenefit": "",
+                                        "title": "The Return of the King",
+                                    },
                                 },
                                 {
-                                    'cursor': 'Mg==',
-                                    'node': {
-                                        'body': 'Long story short: we got the Ring!',
-                                        'date': '2018-01-01 00:00:00+00:00',
-                                        'extra': None,
-                                        'id': 'UmVwb3J0OjE=',
-                                        'isDraft': False,
-                                        'otherParticipants': 'Saruman',
-                                        'ourParticipants': 'Frodo, Gandalf',
-                                        'providedBenefit': '',
-                                        'published': '2018-01-02 00:00:00+00:00',
-                                        'receivedBenefit': 'The Ring',
-                                        'title': 'The Fellowship of the Ring'
-                                    }
-                                }
+                                    "cursor": "Mg==",
+                                    "node": {
+                                        "body": "Long story short: we got the Ring!",
+                                        "date": "2018-01-01 00:00:00+00:00",
+                                        "extra": None,
+                                        "id": "UmVwb3J0OjE=",
+                                        "isDraft": False,
+                                        "otherParticipants": "Saruman",
+                                        "ourParticipants": "Frodo, Gandalf",
+                                        "providedBenefit": "",
+                                        "published": "2018-01-02 00:00:00+00:00",
+                                        "receivedBenefit": "The Ring",
+                                        "title": "The Fellowship of the Ring",
+                                    },
+                                },
                             ],
-                            'totalCount': 2
+                            "totalCount": 2,
                         },
-                        'totalReports': 2
+                        "totalReports": 2,
                     }
-                }
+                },
             ]
         }
     }
 }
 
-snapshots['test_sort_by_last_name 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_sort_by_last_name 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_sort_by_last_name_reversed 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_sort_by_last_name_reversed 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_sort_by_total_reports 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_sort_by_total_reports 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_sort_by_total_reports_reversed 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_sort_by_total_reports_reversed 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_sort_by_default_reversed 1'] = {
-    'data': {
-        'authors': {
-            'edges': [
+snapshots["test_sort_by_default_reversed 1"] = {
+    "data": {
+        "authors": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'extra': '{"movies": 1}',
-                        'firstName': 'Winston',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjE=',
-                        'lastName': 'Wolfe',
-                        'totalReports': 2
-                    }
+                    "cursor": "MQ==",
+                    "node": {
+                        "extra": '{"movies": 1}',
+                        "firstName": "Winston",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjE=",
+                        "lastName": "Wolfe",
+                        "totalReports": 2,
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Spongebob',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjI=',
-                        'lastName': 'Squarepants',
-                        'totalReports': 1
-                    }
+                    "cursor": "Mg==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Spongebob",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjI=",
+                        "lastName": "Squarepants",
+                        "totalReports": 1,
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'extra': None,
-                        'firstName': 'Shaun',
-                        'hasCollidingName': False,
-                        'id': 'QXV0aG9yOjM=',
-                        'lastName': 'Sheep',
-                        'totalReports': 0
-                    }
-                }
+                    "cursor": "Mw==",
+                    "node": {
+                        "extra": None,
+                        "firstName": "Shaun",
+                        "hasCollidingName": False,
+                        "id": "QXV0aG9yOjM=",
+                        "lastName": "Sheep",
+                        "totalReports": 0,
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
diff --git a/tests/schema/snapshots/snap_test_login_shortcuts.py b/tests/schema/snapshots/snap_test_login_shortcuts.py
index 45cc81f6b986dea6fce412ac8a51a807bc57c7ad..252a4f8a88c43f42909ff3e1aa71db12435dd698 100644
--- a/tests/schema/snapshots/snap_test_login_shortcuts.py
+++ b/tests/schema/snapshots/snap_test_login_shortcuts.py
@@ -7,20 +7,8 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_returns_only_shortcuts 1'] = {
-    'data': {
-        'loginShortcuts': [
-            {
-                'id': 'TG9naW5TaG9ydGN1dDoyMA==',
-                'name': 'bar'
-            }
-        ]
-    }
+snapshots["test_returns_only_shortcuts 1"] = {
+    "data": {"loginShortcuts": [{"id": "TG9naW5TaG9ydGN1dDoyMA==", "name": "bar"}]}
 }
 
-snapshots['test_none 1'] = {
-    'data': {
-        'loginShortcuts': [
-        ]
-    }
-}
+snapshots["test_none 1"] = {"data": {"loginShortcuts": []}}
diff --git a/tests/schema/snapshots/snap_test_node.py b/tests/schema/snapshots/snap_test_node.py
index 018addc9a0cdf7554650be7d7cd9d1e52f746809..91a0da5bbcb43c6c9b611b80b25dc02691ee9c63 100644
--- a/tests/schema/snapshots/snap_test_node.py
+++ b/tests/schema/snapshots/snap_test_node.py
@@ -7,104 +7,75 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_login_shortcut 1'] = {
-    'data': {
-        'node': {
-            'id': 'TG9naW5TaG9ydGN1dDoxMA==',
-            'name': 'foo'
-        }
-    }
+snapshots["test_login_shortcut 1"] = {
+    "data": {"node": {"id": "TG9naW5TaG9ydGN1dDoxMA==", "name": "foo"}}
 }
 
-snapshots['test_author 1'] = {
-    'data': {
-        'node': {
-            'extra': '{"movies": 1}',
-            'firstName': 'Winston',
-            'hasCollidingName': False,
-            'id': 'QXV0aG9yOjE=',
-            'lastName': 'Wolfe',
-            'totalReports': 2
+snapshots["test_author 1"] = {
+    "data": {
+        "node": {
+            "extra": '{"movies": 1}',
+            "firstName": "Winston",
+            "hasCollidingName": False,
+            "id": "QXV0aG9yOjE=",
+            "lastName": "Wolfe",
+            "totalReports": 2,
         }
     }
 }
 
-snapshots['test_author__returns_only_if_is_author 1'] = {
-    'data': {
-        'node': None
-    }
-}
+snapshots["test_author__returns_only_if_is_author 1"] = {"data": {"node": None}}
 
-snapshots['test_report 1'] = {
-    'data': {
-        'node': {
-            'author': {
-                'extra': '{"movies": 1}',
-                'firstName': 'Winston',
-                'hasCollidingName': False,
-                'id': 'QXV0aG9yOjE=',
-                'lastName': 'Wolfe',
-                'totalReports': 2
+snapshots["test_report 1"] = {
+    "data": {
+        "node": {
+            "author": {
+                "extra": '{"movies": 1}',
+                "firstName": "Winston",
+                "hasCollidingName": False,
+                "id": "QXV0aG9yOjE=",
+                "lastName": "Wolfe",
+                "totalReports": 2,
             },
-            'body': 'Long story short: we got the Ring!',
-            'date': '2018-01-01 00:00:00+00:00',
-            'extra': None,
-            'id': 'UmVwb3J0OjE=',
-            'isDraft': False,
-            'otherParticipants': 'Saruman',
-            'ourParticipants': 'Frodo, Gandalf',
-            'providedBenefit': '',
-            'published': '2018-01-02 00:00:00+00:00',
-            'receivedBenefit': 'The Ring',
-            'title': 'The Fellowship of the Ring'
+            "body": "Long story short: we got the Ring!",
+            "date": "2018-01-01 00:00:00+00:00",
+            "extra": None,
+            "id": "UmVwb3J0OjE=",
+            "isDraft": False,
+            "otherParticipants": "Saruman",
+            "ourParticipants": "Frodo, Gandalf",
+            "providedBenefit": "",
+            "published": "2018-01-02 00:00:00+00:00",
+            "receivedBenefit": "The Ring",
+            "title": "The Fellowship of the Ring",
         }
     }
 }
 
-snapshots['test_user__unauthorized 1'] = {
-    'data': {
-        'node': None
-    }
-}
+snapshots["test_user__unauthorized 1"] = {"data": {"node": None}}
 
-snapshots['test_user__not_a_viewer 1'] = {
-    'data': {
-        'node': None
-    }
-}
+snapshots["test_user__not_a_viewer 1"] = {"data": {"node": None}}
 
-snapshots['test_user 1'] = {
-    'data': {
-        'node': {
-            'extra': '{"e": "mc2"}',
-            'firstName': 'Albert',
-            'hasCollidingName': False,
-            'id': 'VXNlcjo4',
-            'isAuthor': False,
-            'lastName': 'Einstein',
-            'openidUid': 'albert@einstein.id'
+snapshots["test_user 1"] = {
+    "data": {
+        "node": {
+            "extra": '{"e": "mc2"}',
+            "firstName": "Albert",
+            "hasCollidingName": False,
+            "id": "VXNlcjo4",
+            "isAuthor": False,
+            "lastName": "Einstein",
+            "openidUid": "albert@einstein.id",
         }
     }
 }
 
-snapshots['test_report__is_draft__unauthorized_viewer 1'] = {
-    'data': {
-        'node': None
-    }
-}
+snapshots["test_report__is_draft__unauthorized_viewer 1"] = {"data": {"node": None}}
 
-snapshots['test_report__is_draft__viewer_is_not_author 1'] = {
-    'data': {
-        'node': None
-    }
-}
+snapshots["test_report__is_draft__viewer_is_not_author 1"] = {"data": {"node": None}}
 
-snapshots['test_report__is_draft 1'] = {
-    'data': {
-        'node': {
-            'id': 'UmVwb3J0OjQ=',
-            'isDraft': True,
-            'title': 'The Silmarillion'
-        }
+snapshots["test_report__is_draft 1"] = {
+    "data": {
+        "node": {"id": "UmVwb3J0OjQ=", "isDraft": True, "title": "The Silmarillion"}
     }
 }
diff --git a/tests/schema/snapshots/snap_test_report_drafts.py b/tests/schema/snapshots/snap_test_report_drafts.py
index a589b1b002c61b060e475fe6502660e652c2835c..1106c70e57b89e78676c395306c2effbae3912a3 100644
--- a/tests/schema/snapshots/snap_test_report_drafts.py
+++ b/tests/schema/snapshots/snap_test_report_drafts.py
@@ -7,27 +7,22 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_unauthenticated 1'] = {
-    'data': {
-        'reportDrafts': [
-        ]
-    }
-}
+snapshots["test_unauthenticated 1"] = {"data": {"reportDrafts": []}}
 
-snapshots['test_authenticated 1'] = {
-    'data': {
-        'reportDrafts': [
+snapshots["test_authenticated 1"] = {
+    "data": {
+        "reportDrafts": [
             {
-                'body': 'Not finished yet.',
-                'date': '2018-01-07 00:00:00+00:00',
-                'id': 'UmVwb3J0OjQ=',
-                'isDraft': True,
-                'otherParticipants': '',
-                'ourParticipants': '',
-                'providedBenefit': '',
-                'published': '2018-01-08 00:00:00+00:00',
-                'receivedBenefit': '',
-                'title': 'The Silmarillion'
+                "body": "Not finished yet.",
+                "date": "2018-01-07 00:00:00+00:00",
+                "id": "UmVwb3J0OjQ=",
+                "isDraft": True,
+                "otherParticipants": "",
+                "ourParticipants": "",
+                "providedBenefit": "",
+                "published": "2018-01-08 00:00:00+00:00",
+                "receivedBenefit": "",
+                "title": "The Silmarillion",
             }
         ]
     }
diff --git a/tests/schema/snapshots/snap_test_search_reports.py b/tests/schema/snapshots/snap_test_search_reports.py
index ef7aaa956987b600455a896fc2e37defeb17a700..b0c0e30482c93afca389f9729aa922f341454aaa 100644
--- a/tests/schema/snapshots/snap_test_search_reports.py
+++ b/tests/schema/snapshots/snap_test_search_reports.py
@@ -7,268 +7,252 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_all 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_all 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'author': {
-                            'extra': '{"movies": 1}',
-                            'firstName': 'Winston',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjE=',
-                            'lastName': 'Wolfe',
-                            'totalReports': 2
+                    "cursor": "MQ==",
+                    "node": {
+                        "author": {
+                            "extra": '{"movies": 1}',
+                            "firstName": "Winston",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjE=",
+                            "lastName": "Wolfe",
+                            "totalReports": 2,
                         },
-                        'body': 'Aragorn is the King. And we have lost the Ring.',
-                        'date': '2018-01-05 00:00:00+00:00',
-                        'extra': None,
-                        'id': 'UmVwb3J0OjM=',
-                        'isDraft': False,
-                        'otherParticipants': 'Sauron',
-                        'ourParticipants': 'Aragorn',
-                        'providedBenefit': 'The Ring',
-                        'published': '2018-01-06 00:00:00+00:00',
-                        'receivedBenefit': '',
-                        'title': 'The Return of the King'
-                    }
+                        "body": "Aragorn is the King. And we have lost the Ring.",
+                        "date": "2018-01-05 00:00:00+00:00",
+                        "extra": None,
+                        "id": "UmVwb3J0OjM=",
+                        "isDraft": False,
+                        "otherParticipants": "Sauron",
+                        "ourParticipants": "Aragorn",
+                        "providedBenefit": "The Ring",
+                        "published": "2018-01-06 00:00:00+00:00",
+                        "receivedBenefit": "",
+                        "title": "The Return of the King",
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'author': {
-                            'extra': None,
-                            'firstName': 'Spongebob',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjI=',
-                            'lastName': 'Squarepants',
-                            'totalReports': 1
+                    "cursor": "Mg==",
+                    "node": {
+                        "author": {
+                            "extra": None,
+                            "firstName": "Spongebob",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjI=",
+                            "lastName": "Squarepants",
+                            "totalReports": 1,
                         },
-                        'body': 'Another long story.',
-                        'date': '2018-01-03 00:00:00+00:00',
-                        'extra': '{"rings": 1}',
-                        'id': 'UmVwb3J0OjI=',
-                        'isDraft': False,
-                        'otherParticipants': 'Saruman, Sauron',
-                        'ourParticipants': 'Frodo, Gimli, Legolas',
-                        'providedBenefit': '',
-                        'published': '2018-01-04 00:00:00+00:00',
-                        'receivedBenefit': 'Mithrill Jacket',
-                        'title': 'The Two Towers'
-                    }
+                        "body": "Another long story.",
+                        "date": "2018-01-03 00:00:00+00:00",
+                        "extra": '{"rings": 1}',
+                        "id": "UmVwb3J0OjI=",
+                        "isDraft": False,
+                        "otherParticipants": "Saruman, Sauron",
+                        "ourParticipants": "Frodo, Gimli, Legolas",
+                        "providedBenefit": "",
+                        "published": "2018-01-04 00:00:00+00:00",
+                        "receivedBenefit": "Mithrill Jacket",
+                        "title": "The Two Towers",
+                    },
                 },
                 {
-                    'cursor': 'Mw==',
-                    'node': {
-                        'author': {
-                            'extra': '{"movies": 1}',
-                            'firstName': 'Winston',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjE=',
-                            'lastName': 'Wolfe',
-                            'totalReports': 2
+                    "cursor": "Mw==",
+                    "node": {
+                        "author": {
+                            "extra": '{"movies": 1}',
+                            "firstName": "Winston",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjE=",
+                            "lastName": "Wolfe",
+                            "totalReports": 2,
                         },
-                        'body': 'Long story short: we got the Ring!',
-                        'date': '2018-01-01 00:00:00+00:00',
-                        'extra': None,
-                        'id': 'UmVwb3J0OjE=',
-                        'isDraft': False,
-                        'otherParticipants': 'Saruman',
-                        'ourParticipants': 'Frodo, Gandalf',
-                        'providedBenefit': '',
-                        'published': '2018-01-02 00:00:00+00:00',
-                        'receivedBenefit': 'The Ring',
-                        'title': 'The Fellowship of the Ring'
-                    }
-                }
+                        "body": "Long story short: we got the Ring!",
+                        "date": "2018-01-01 00:00:00+00:00",
+                        "extra": None,
+                        "id": "UmVwb3J0OjE=",
+                        "isDraft": False,
+                        "otherParticipants": "Saruman",
+                        "ourParticipants": "Frodo, Gandalf",
+                        "providedBenefit": "",
+                        "published": "2018-01-02 00:00:00+00:00",
+                        "receivedBenefit": "The Ring",
+                        "title": "The Fellowship of the Ring",
+                    },
+                },
             ],
-            'pageInfo': {
-                'endCursor': 'Mw==',
-                'hasNextPage': False,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "Mw==",
+                "hasNextPage": False,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_query 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_query 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'author': {
-                            'extra': None,
-                            'firstName': 'Spongebob',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjI=',
-                            'lastName': 'Squarepants',
-                            'totalReports': 1
+                    "cursor": "MQ==",
+                    "node": {
+                        "author": {
+                            "extra": None,
+                            "firstName": "Spongebob",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjI=",
+                            "lastName": "Squarepants",
+                            "totalReports": 1,
                         },
-                        'body': 'Another long story.',
-                        'date': '2018-01-03 00:00:00+00:00',
-                        'extra': '{"rings": 1}',
-                        'id': 'UmVwb3J0OjI=',
-                        'isDraft': False,
-                        'otherParticipants': 'Saruman, Sauron',
-                        'ourParticipants': 'Frodo, Gimli, Legolas',
-                        'providedBenefit': '',
-                        'published': '2018-01-04 00:00:00+00:00',
-                        'receivedBenefit': 'Mithrill Jacket',
-                        'title': 'The Two Towers'
-                    }
+                        "body": "Another long story.",
+                        "date": "2018-01-03 00:00:00+00:00",
+                        "extra": '{"rings": 1}',
+                        "id": "UmVwb3J0OjI=",
+                        "isDraft": False,
+                        "otherParticipants": "Saruman, Sauron",
+                        "ourParticipants": "Frodo, Gimli, Legolas",
+                        "providedBenefit": "",
+                        "published": "2018-01-04 00:00:00+00:00",
+                        "receivedBenefit": "Mithrill Jacket",
+                        "title": "The Two Towers",
+                    },
                 }
             ],
-            'totalCount': 1
+            "totalCount": 1,
         }
     }
 }
 
-snapshots['test_highlight 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_highlight 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'author': {
-                            'extra': '{"movies": 1}',
-                            'firstName': 'Winston',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjE=',
-                            'lastName': 'Wolfe',
-                            'totalReports': 2
+                    "cursor": "MQ==",
+                    "node": {
+                        "author": {
+                            "extra": '{"movies": 1}',
+                            "firstName": "Winston",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjE=",
+                            "lastName": "Wolfe",
+                            "totalReports": 2,
                         },
-                        'body': 'Aragorn is the King. And we have lost the <mark>Ring</mark>.',
-                        'date': '2018-01-05 00:00:00+00:00',
-                        'extra': None,
-                        'id': 'UmVwb3J0OjM=',
-                        'isDraft': False,
-                        'otherParticipants': 'Sauron',
-                        'ourParticipants': 'Aragorn',
-                        'providedBenefit': 'The <mark>Ring</mark>',
-                        'published': '2018-01-06 00:00:00+00:00',
-                        'receivedBenefit': '',
-                        'title': 'The Return of the King'
-                    }
+                        "body": "Aragorn is the King. And we have lost the <mark>Ring</mark>.",
+                        "date": "2018-01-05 00:00:00+00:00",
+                        "extra": None,
+                        "id": "UmVwb3J0OjM=",
+                        "isDraft": False,
+                        "otherParticipants": "Sauron",
+                        "ourParticipants": "Aragorn",
+                        "providedBenefit": "The <mark>Ring</mark>",
+                        "published": "2018-01-06 00:00:00+00:00",
+                        "receivedBenefit": "",
+                        "title": "The Return of the King",
+                    },
                 },
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'author': {
-                            'extra': '{"movies": 1}',
-                            'firstName': 'Winston',
-                            'hasCollidingName': False,
-                            'id': 'QXV0aG9yOjE=',
-                            'lastName': 'Wolfe',
-                            'totalReports': 2
+                    "cursor": "Mg==",
+                    "node": {
+                        "author": {
+                            "extra": '{"movies": 1}',
+                            "firstName": "Winston",
+                            "hasCollidingName": False,
+                            "id": "QXV0aG9yOjE=",
+                            "lastName": "Wolfe",
+                            "totalReports": 2,
                         },
-                        'body': 'Long story short: we got the <mark>Ring</mark>!',
-                        'date': '2018-01-01 00:00:00+00:00',
-                        'extra': None,
-                        'id': 'UmVwb3J0OjE=',
-                        'isDraft': False,
-                        'otherParticipants': 'Saruman',
-                        'ourParticipants': 'Frodo, Gandalf',
-                        'providedBenefit': '',
-                        'published': '2018-01-02 00:00:00+00:00',
-                        'receivedBenefit': 'The <mark>Ring</mark>',
-                        'title': 'The Fellowship of the <mark>Ring</mark>'
-                    }
-                }
+                        "body": "Long story short: we got the <mark>Ring</mark>!",
+                        "date": "2018-01-01 00:00:00+00:00",
+                        "extra": None,
+                        "id": "UmVwb3J0OjE=",
+                        "isDraft": False,
+                        "otherParticipants": "Saruman",
+                        "ourParticipants": "Frodo, Gandalf",
+                        "providedBenefit": "",
+                        "published": "2018-01-02 00:00:00+00:00",
+                        "receivedBenefit": "The <mark>Ring</mark>",
+                        "title": "The Fellowship of the <mark>Ring</mark>",
+                    },
+                },
             ],
-            'totalCount': 2
+            "totalCount": 2,
         }
     }
 }
 
-snapshots['test_first 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_first 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'MQ==',
-                    'node': {
-                        'id': 'UmVwb3J0OjM=',
-                        'title': 'The Return of the King'
-                    }
+                    "cursor": "MQ==",
+                    "node": {"id": "UmVwb3J0OjM=", "title": "The Return of the King"},
                 }
             ],
-            'pageInfo': {
-                'endCursor': 'MQ==',
-                'hasNextPage': True,
-                'hasPreviousPage': False,
-                'startCursor': 'MQ=='
+            "pageInfo": {
+                "endCursor": "MQ==",
+                "hasNextPage": True,
+                "hasPreviousPage": False,
+                "startCursor": "MQ==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_first_after 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_first_after 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'id': 'UmVwb3J0OjI=',
-                        'title': 'The Two Towers'
-                    }
+                    "cursor": "Mg==",
+                    "node": {"id": "UmVwb3J0OjI=", "title": "The Two Towers"},
                 }
             ],
-            'pageInfo': {
-                'endCursor': 'Mg==',
-                'hasNextPage': True,
-                'hasPreviousPage': True,
-                'startCursor': 'Mg=='
+            "pageInfo": {
+                "endCursor": "Mg==",
+                "hasNextPage": True,
+                "hasPreviousPage": True,
+                "startCursor": "Mg==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
 
-snapshots['test_last 1'] = {
-    'data': {
-        'searchReports': None
-    },
-    'errors': [
+snapshots["test_last 1"] = {
+    "data": {"searchReports": None},
+    "errors": [
         {
-            'locations': [
-                {
-                    'column': 9,
-                    'line': 3
-                }
-            ],
-            'message': 'Pagination "last" works only in combination with "before" argument.'
+            "locations": [{"column": 9, "line": 3}],
+            "message": 'Pagination "last" works only in combination with "before" argument.',
         }
-    ]
+    ],
 }
 
-snapshots['test_last_before 1'] = {
-    'data': {
-        'searchReports': {
-            'edges': [
+snapshots["test_last_before 1"] = {
+    "data": {
+        "searchReports": {
+            "edges": [
                 {
-                    'cursor': 'Mg==',
-                    'node': {
-                        'id': 'UmVwb3J0OjI=',
-                        'title': 'The Two Towers'
-                    }
+                    "cursor": "Mg==",
+                    "node": {"id": "UmVwb3J0OjI=", "title": "The Two Towers"},
                 }
             ],
-            'pageInfo': {
-                'endCursor': 'Mg==',
-                'hasNextPage': True,
-                'hasPreviousPage': True,
-                'startCursor': 'Mg=='
+            "pageInfo": {
+                "endCursor": "Mg==",
+                "hasNextPage": True,
+                "hasPreviousPage": True,
+                "startCursor": "Mg==",
             },
-            'totalCount': 3
+            "totalCount": 3,
         }
     }
 }
diff --git a/tests/schema/snapshots/snap_test_viewer.py b/tests/schema/snapshots/snap_test_viewer.py
index fb88edfc1557b7f419ab91d39a872731cc332863..326a64bdc6a7d9c6726f34aa01b973b34fafe144 100644
--- a/tests/schema/snapshots/snap_test_viewer.py
+++ b/tests/schema/snapshots/snap_test_viewer.py
@@ -7,45 +7,27 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_unauthenticated 1'] = {
-    'data': {
-        'viewer': None
-    }
-}
-
-snapshots['test_authenticated 1'] = {
-    'data': {
-        'viewer': {
-            'email': 'winston@wolfe.com',
-            'extra': '{"caliber": 45}',
-            'firstName': 'Winston',
-            'hasCollidingName': False,
-            'id': 'VXNlcjox',
-            'isAuthor': True,
-            'lastName': 'Wolfe',
-            'openidUid': 'TheWolf'
+snapshots["test_unauthenticated 1"] = {"data": {"viewer": None}}
+
+snapshots["test_authenticated 1"] = {
+    "data": {
+        "viewer": {
+            "email": "winston@wolfe.com",
+            "extra": '{"caliber": 45}',
+            "firstName": "Winston",
+            "hasCollidingName": False,
+            "id": "VXNlcjox",
+            "isAuthor": True,
+            "lastName": "Wolfe",
+            "openidUid": "TheWolf",
         }
     }
 }
 
-snapshots['test_wrong_header 1'] = {
-    'errors': [
-        {
-            'message': 'Wrong Authorization header. Expected: "Bearer <token>"'
-        }
-    ]
+snapshots["test_wrong_header 1"] = {
+    "errors": [{"message": 'Wrong Authorization header. Expected: "Bearer <token>"'}]
 }
 
-snapshots['test_wrong_token 1'] = {
-    'errors': [
-        {
-            'message': 'Invalid Token.'
-        }
-    ]
-}
+snapshots["test_wrong_token 1"] = {"errors": [{"message": "Invalid Token."}]}
 
-snapshots['test_unknown_user 1'] = {
-    'data': {
-        'viewer': None
-    }
-}
+snapshots["test_unknown_user 1"] = {"data": {"viewer": None}}
diff --git a/tests/schema/test_authors.py b/tests/schema/test_authors.py
index 5c59a37386187dff0949ef7bb8dedee57d827897..3d4bb07a7a857f0b383e7da94cba8c6dd01d3066 100644
--- a/tests/schema/test_authors.py
+++ b/tests/schema/test_authors.py
@@ -6,12 +6,12 @@ from ..dummy import prepare_reports
 from ..utils import call_api
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 def test_all(client, snapshot):
     prepare_reports()
-    User.objects.create(id=4, is_author=False, username='x')
+    User.objects.create(id=4, is_author=False, username="x")
     query = """
     query {
         authors {
@@ -200,6 +200,7 @@ def test_with_reports(client, snapshot):
     response = call_api(client, query)
     snapshot.assert_match(response)
 
+
 def test_sort_by_last_name(client, snapshot):
     prepare_reports()
     query = """
@@ -229,6 +230,7 @@ def test_sort_by_last_name(client, snapshot):
     response = call_api(client, query)
     snapshot.assert_match(response)
 
+
 def test_sort_by_last_name_reversed(client, snapshot):
     prepare_reports()
     query = """
@@ -258,6 +260,7 @@ def test_sort_by_last_name_reversed(client, snapshot):
     response = call_api(client, query)
     snapshot.assert_match(response)
 
+
 def test_sort_by_total_reports(client, snapshot):
     prepare_reports()
     query = """
@@ -287,6 +290,7 @@ def test_sort_by_total_reports(client, snapshot):
     response = call_api(client, query)
     snapshot.assert_match(response)
 
+
 def test_sort_by_total_reports_reversed(client, snapshot):
     prepare_reports()
     query = """
@@ -316,6 +320,7 @@ def test_sort_by_total_reports_reversed(client, snapshot):
     response = call_api(client, query)
     snapshot.assert_match(response)
 
+
 def test_sort_by_default_reversed(client, snapshot):
     prepare_reports()
     query = """
@@ -343,4 +348,4 @@ def test_sort_by_default_reversed(client, snapshot):
     }
     """
     response = call_api(client, query)
-    snapshot.assert_match(response)
\ No newline at end of file
+    snapshot.assert_match(response)
diff --git a/tests/schema/test_login_shortcuts.py b/tests/schema/test_login_shortcuts.py
index 2b0ad968eb6ccffe8a6da89c099ac21cb2fc3174..4ec90abd615e15c5cc1b12c35e9cdfc831e2212f 100644
--- a/tests/schema/test_login_shortcuts.py
+++ b/tests/schema/test_login_shortcuts.py
@@ -9,8 +9,8 @@ pytestmark = pytest.mark.django_db
 
 
 def test_returns_only_shortcuts(client, snapshot):
-    OpenIdClient.objects.create(id=10, name='foo', issuer='foo')
-    OpenIdClient.objects.create(id=20, name='bar', issuer='bar', is_shortcut=True)
+    OpenIdClient.objects.create(id=10, name="foo", issuer="foo")
+    OpenIdClient.objects.create(id=20, name="bar", issuer="bar", is_shortcut=True)
     query = """
     query {
         loginShortcuts {
@@ -24,7 +24,7 @@ def test_returns_only_shortcuts(client, snapshot):
 
 
 def test_none(client, snapshot):
-    OpenIdClient.objects.create(id=10, name='foo')
+    OpenIdClient.objects.create(id=10, name="foo")
     query = """
     query {
         loginShortcuts {
diff --git a/tests/schema/test_node.py b/tests/schema/test_node.py
index 6a42cb509207607c73355a05d332f7e707ae2d48..f13de1239c25b1b3de54b82906df11b18fd179d9 100644
--- a/tests/schema/test_node.py
+++ b/tests/schema/test_node.py
@@ -7,11 +7,11 @@ from ..dummy import prepare_reports
 from ..utils import call_api
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 def test_login_shortcut(client, snapshot):
-    OpenIdClient.objects.create(id=10, name='foo', issuer='foo', is_shortcut=True)
+    OpenIdClient.objects.create(id=10, name="foo", issuer="foo", is_shortcut=True)
     query = """
     query {{
         node (id:"{id}") {{
@@ -21,7 +21,9 @@ def test_login_shortcut(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('LoginShortcut', 10))
+    """.format(
+        id=to_global_id("LoginShortcut", 10)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
@@ -41,7 +43,9 @@ def test_author(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Author', 1))
+    """.format(
+        id=to_global_id("Author", 1)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
@@ -56,7 +60,9 @@ def test_author__returns_only_if_is_author(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Author', 7))
+    """.format(
+        id=to_global_id("Author", 7)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
@@ -89,7 +95,9 @@ def test_report(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Report', 1))
+    """.format(
+        id=to_global_id("Report", 1)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
@@ -106,8 +114,10 @@ def test_report__is_draft(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Report', 4))
-    response = call_api(client, query, username='wolf')
+    """.format(
+        id=to_global_id("Report", 4)
+    )
+    response = call_api(client, query, username="wolf")
     snapshot.assert_match(response)
 
 
@@ -123,7 +133,9 @@ def test_report__is_draft__unauthorized_viewer(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Report', 4))
+    """.format(
+        id=to_global_id("Report", 4)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
@@ -140,14 +152,22 @@ def test_report__is_draft__viewer_is_not_author(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('Report', 4))
-    response = call_api(client, query, username='spongebob')
+    """.format(
+        id=to_global_id("Report", 4)
+    )
+    response = call_api(client, query, username="spongebob")
     snapshot.assert_match(response)
 
 
 def test_user__unauthorized(client, snapshot):
-    User.objects.create(id=8, username='albert', openid_uid='albert@einstein.id',
-        first_name='Albert', last_name='Einstein', extra={'e': 'mc2'})
+    User.objects.create(
+        id=8,
+        username="albert",
+        openid_uid="albert@einstein.id",
+        first_name="Albert",
+        last_name="Einstein",
+        extra={"e": "mc2"},
+    )
     query = """
     query {{
         node (id:"{id}") {{
@@ -162,16 +182,30 @@ def test_user__unauthorized(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('User', 8))
+    """.format(
+        id=to_global_id("User", 8)
+    )
     response = call_api(client, query)
     snapshot.assert_match(response)
 
 
 def test_user__not_a_viewer(client, snapshot):
-    User.objects.create(id=8, username='albert', openid_uid='albert@einstein.id',
-        first_name='Albert', last_name='Einstein', extra={'e': 'mc2'})
-    User.objects.create(id=2, username='isaac', openid_uid='isaac@newton.id',
-        first_name='Isaac', last_name='Newton', extra={'apple': 'hit'})
+    User.objects.create(
+        id=8,
+        username="albert",
+        openid_uid="albert@einstein.id",
+        first_name="Albert",
+        last_name="Einstein",
+        extra={"e": "mc2"},
+    )
+    User.objects.create(
+        id=2,
+        username="isaac",
+        openid_uid="isaac@newton.id",
+        first_name="Isaac",
+        last_name="Newton",
+        extra={"apple": "hit"},
+    )
     query = """
     query {{
         node (id:"{id}") {{
@@ -186,14 +220,22 @@ def test_user__not_a_viewer(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('User', 8))
-    response = call_api(client, query, username='isaac')
+    """.format(
+        id=to_global_id("User", 8)
+    )
+    response = call_api(client, query, username="isaac")
     snapshot.assert_match(response)
 
 
 def test_user(client, snapshot):
-    User.objects.create(id=8, username='albert', openid_uid='albert@einstein.id',
-            first_name='Albert', last_name='Einstein', extra={'e': 'mc2'})
+    User.objects.create(
+        id=8,
+        username="albert",
+        openid_uid="albert@einstein.id",
+        first_name="Albert",
+        last_name="Einstein",
+        extra={"e": "mc2"},
+    )
     query = """
     query {{
         node (id:"{id}") {{
@@ -208,6 +250,8 @@ def test_user(client, snapshot):
             }}
         }}
     }}
-    """.format(id=to_global_id('User', 8))
-    response = call_api(client, query, username='albert')
+    """.format(
+        id=to_global_id("User", 8)
+    )
+    response = call_api(client, query, username="albert")
     snapshot.assert_match(response)
diff --git a/tests/schema/test_report_drafts.py b/tests/schema/test_report_drafts.py
index 81898755a2bff62ffdccc45fc63c85f8ddb0b680..013f6dab0c1b5e65ce06eb338f3ce830a94a8a3c 100644
--- a/tests/schema/test_report_drafts.py
+++ b/tests/schema/test_report_drafts.py
@@ -4,7 +4,7 @@ from ..dummy import prepare_reports
 from ..utils import call_api
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 def test_unauthenticated(client, snapshot):
@@ -38,5 +38,5 @@ def test_authenticated(client, snapshot):
         }
     }
     """
-    response = call_api(client, query, username='wolf')
+    response = call_api(client, query, username="wolf")
     snapshot.assert_match(response)
diff --git a/tests/schema/test_search_reports.py b/tests/schema/test_search_reports.py
index 4da763b95db5203a1a302fee74f69b67079536d7..68cbd11e76d8416281597cf1adbee8447c9df415 100644
--- a/tests/schema/test_search_reports.py
+++ b/tests/schema/test_search_reports.py
@@ -4,7 +4,7 @@ from ..dummy import prepare_reports
 from ..utils import call_api
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 def test_all(client, snapshot):
diff --git a/tests/schema/test_viewer.py b/tests/schema/test_viewer.py
index 3895debd1ea53ba632191471810acc7f99348912..1255eff15f9147a4f5585bc3bb765e8a24a638b9 100644
--- a/tests/schema/test_viewer.py
+++ b/tests/schema/test_viewer.py
@@ -11,9 +11,16 @@ pytestmark = pytest.mark.django_db
 
 @pytest.fixture(autouse=True)
 def setup():
-    User.objects.create(id=1, is_author=True, username='wolf', openid_uid='TheWolf',
-        first_name='Winston', last_name='Wolfe', email='winston@wolfe.com',
-        extra={'caliber': 45})
+    User.objects.create(
+        id=1,
+        is_author=True,
+        username="wolf",
+        openid_uid="TheWolf",
+        first_name="Winston",
+        last_name="Wolfe",
+        email="winston@wolfe.com",
+        extra={"caliber": 45},
+    )
 
 
 def test_unauthenticated(client, snapshot):
@@ -43,46 +50,65 @@ def test_authenticated(client, snapshot):
         }
     }
     """
-    response = call_api(client, query, username='wolf')
+    response = call_api(client, query, username="wolf")
     snapshot.assert_match(response)
 
 
 # integration tests of wrong authentication
 
+
 def test_wrong_header(client, snapshot):
-    token = create_access_token('wolfe')
-    auth_header = 'WRONG {}'.format(token)
-    res = client.post('/graphql', {'query': """
+    token = create_access_token("wolfe")
+    auth_header = "WRONG {}".format(token)
+    res = client.post(
+        "/graphql",
+        {
+            "query": """
     query {
         viewer {
             id
         }
     }
-    """}, HTTP_AUTHORIZATION=auth_header)
+    """
+        },
+        HTTP_AUTHORIZATION=auth_header,
+    )
     snapshot.assert_match(res.json())
 
 
 def test_wrong_token(client, snapshot):
-    token = create_access_token('wolfe')
-    auth_header = 'Bearer XXX{}'.format(token)
-    res = client.post('/graphql', {'query': """
+    token = create_access_token("wolfe")
+    auth_header = "Bearer XXX{}".format(token)
+    res = client.post(
+        "/graphql",
+        {
+            "query": """
     query {
         viewer {
             id
         }
     }
-    """}, HTTP_AUTHORIZATION=auth_header)
+    """
+        },
+        HTTP_AUTHORIZATION=auth_header,
+    )
     snapshot.assert_match(res.json())
 
 
 def test_unknown_user(client, snapshot):
-    token = create_access_token('unknown')
-    auth_header = 'Bearer {}'.format(token)
-    res = client.post('/graphql', {'query': """
+    token = create_access_token("unknown")
+    auth_header = "Bearer {}".format(token)
+    res = client.post(
+        "/graphql",
+        {
+            "query": """
     query {
         viewer {
             id
         }
     }
-    """}, HTTP_AUTHORIZATION=auth_header)
+    """
+        },
+        HTTP_AUTHORIZATION=auth_header,
+    )
     snapshot.assert_match(res.json())
diff --git a/tests/snapshots/snap_test_management.py b/tests/snapshots/snap_test_management.py
index ff10ca76366130dd48abf3d4828fa3acb96a314b..5cf4f3f010765d0c0c6232adf25df8487c393c1f 100644
--- a/tests/snapshots/snap_test_management.py
+++ b/tests/snapshots/snap_test_management.py
@@ -7,325 +7,159 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_create_index__check_analysis_settings 1'] = {
-    'analyzer': {
-        'czech': {
-            'filter': [
-                'icu_folding',
-                'lowercase',
-                'czech_synonym',
-                'czech_stop',
-                'czech_stemmer',
-                'cs_CZ'
+snapshots["test_create_index__check_analysis_settings 1"] = {
+    "analyzer": {
+        "czech": {
+            "filter": [
+                "icu_folding",
+                "lowercase",
+                "czech_synonym",
+                "czech_stop",
+                "czech_stemmer",
+                "cs_CZ",
             ],
-            'tokenizer': 'standard'
+            "tokenizer": "standard",
         }
     },
-    'filter': {
-        'cs_CZ': {
-            'dedup': 'true',
-            'locale': 'cs_CZ',
-            'type': 'hunspell'
+    "filter": {
+        "cs_CZ": {"dedup": "true", "locale": "cs_CZ", "type": "hunspell"},
+        "czech_stemmer": {"language": "czech", "type": "stemmer"},
+        "czech_stop": {"stopwords": "_czech_", "type": "stop"},
+        "czech_synonym": {
+            "synonyms_path": "analysis/cs_CZ/synonym.txt",
+            "type": "synonym",
         },
-        'czech_stemmer': {
-            'language': 'czech',
-            'type': 'stemmer'
-        },
-        'czech_stop': {
-            'stopwords': '_czech_',
-            'type': 'stop'
-        },
-        'czech_synonym': {
-            'synonyms_path': 'analysis/cs_CZ/synonym.txt',
-            'type': 'synonym'
-        }
-    }
+    },
 }
 
-snapshots['test_create_index__check_mappings 1'] = {
-    'mappings': {
-        'report': {
-            'properties': {
-                'author_id': {
-                    'type': 'keyword'
-                },
-                'body': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'date': {
-                    'type': 'date'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'other_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'our_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'provided_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'published': {
-                    'type': 'date'
-                },
-                'received_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'title': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                }
+snapshots["test_create_index__check_mappings 1"] = {
+    "mappings": {
+        "report": {
+            "properties": {
+                "author_id": {"type": "keyword"},
+                "body": {"analyzer": "czech", "type": "text"},
+                "date": {"type": "date"},
+                "extra": {"type": "object"},
+                "other_participants": {"analyzer": "czech", "type": "text"},
+                "our_participants": {"analyzer": "czech", "type": "text"},
+                "provided_benefit": {"analyzer": "czech", "type": "text"},
+                "published": {"type": "date"},
+                "received_benefit": {"analyzer": "czech", "type": "text"},
+                "title": {"analyzer": "czech", "type": "text"},
             }
         },
-        'session': {
-            'properties': {
-                'expiration': {
-                    'type': 'integer'
-                },
-                'user_id': {
-                    'type': 'keyword'
-                }
+        "session": {
+            "properties": {
+                "expiration": {"type": "integer"},
+                "user_id": {"type": "keyword"},
             }
         },
-        'user': {
-            'properties': {
-                'email': {
-                    'type': 'keyword'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'name': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'openid_uid': {
-                    'type': 'keyword'
-                }
+        "user": {
+            "properties": {
+                "email": {"type": "keyword"},
+                "extra": {"type": "object"},
+                "name": {"analyzer": "czech", "type": "text"},
+                "openid_uid": {"type": "keyword"},
             }
-        }
+        },
     }
 }
 
-snapshots['test_init_alias 1'] = {
-    'mappings': {
-        'report': {
-            'properties': {
-                'author_id': {
-                    'type': 'keyword'
-                },
-                'body': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'date': {
-                    'type': 'date'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'other_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'our_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'provided_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'published': {
-                    'type': 'date'
-                },
-                'received_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'title': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                }
+snapshots["test_init_alias 1"] = {
+    "mappings": {
+        "report": {
+            "properties": {
+                "author_id": {"type": "keyword"},
+                "body": {"analyzer": "czech", "type": "text"},
+                "date": {"type": "date"},
+                "extra": {"type": "object"},
+                "other_participants": {"analyzer": "czech", "type": "text"},
+                "our_participants": {"analyzer": "czech", "type": "text"},
+                "provided_benefit": {"analyzer": "czech", "type": "text"},
+                "published": {"type": "date"},
+                "received_benefit": {"analyzer": "czech", "type": "text"},
+                "title": {"analyzer": "czech", "type": "text"},
             }
         },
-        'session': {
-            'properties': {
-                'expiration': {
-                    'type': 'integer'
-                },
-                'user_id': {
-                    'type': 'keyword'
-                }
+        "session": {
+            "properties": {
+                "expiration": {"type": "integer"},
+                "user_id": {"type": "keyword"},
             }
         },
-        'user': {
-            'properties': {
-                'email': {
-                    'type': 'keyword'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'name': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'openid_uid': {
-                    'type': 'keyword'
-                }
+        "user": {
+            "properties": {
+                "email": {"type": "keyword"},
+                "extra": {"type": "object"},
+                "name": {"analyzer": "czech", "type": "text"},
+                "openid_uid": {"type": "keyword"},
             }
-        }
+        },
     }
 }
 
-snapshots['test_reindex__check_new_index 1'] = {
-    'mappings': {
-        'report': {
-            'properties': {
-                'author_id': {
-                    'type': 'keyword'
-                },
-                'body': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'date': {
-                    'type': 'date'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'other_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'our_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'provided_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'published': {
-                    'type': 'date'
-                },
-                'received_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'title': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                }
+snapshots["test_reindex__check_new_index 1"] = {
+    "mappings": {
+        "report": {
+            "properties": {
+                "author_id": {"type": "keyword"},
+                "body": {"analyzer": "czech", "type": "text"},
+                "date": {"type": "date"},
+                "extra": {"type": "object"},
+                "other_participants": {"analyzer": "czech", "type": "text"},
+                "our_participants": {"analyzer": "czech", "type": "text"},
+                "provided_benefit": {"analyzer": "czech", "type": "text"},
+                "published": {"type": "date"},
+                "received_benefit": {"analyzer": "czech", "type": "text"},
+                "title": {"analyzer": "czech", "type": "text"},
             }
         },
-        'session': {
-            'properties': {
-                'expiration': {
-                    'type': 'integer'
-                },
-                'user_id': {
-                    'type': 'keyword'
-                }
+        "session": {
+            "properties": {
+                "expiration": {"type": "integer"},
+                "user_id": {"type": "keyword"},
             }
         },
-        'user': {
-            'properties': {
-                'email': {
-                    'type': 'keyword'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'name': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'openid_uid': {
-                    'type': 'keyword'
-                }
+        "user": {
+            "properties": {
+                "email": {"type": "keyword"},
+                "extra": {"type": "object"},
+                "name": {"analyzer": "czech", "type": "text"},
+                "openid_uid": {"type": "keyword"},
             }
-        }
+        },
     }
 }
 
-snapshots['test_init_documents 1'] = {
-    'mappings': {
-        'report': {
-            'properties': {
-                'author_id': {
-                    'type': 'keyword'
-                },
-                'body': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'date': {
-                    'type': 'date'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'other_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'our_participants': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'provided_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'published': {
-                    'type': 'date'
-                },
-                'received_benefit': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'title': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                }
+snapshots["test_init_documents 1"] = {
+    "mappings": {
+        "report": {
+            "properties": {
+                "author_id": {"type": "keyword"},
+                "body": {"analyzer": "czech", "type": "text"},
+                "date": {"type": "date"},
+                "extra": {"type": "object"},
+                "other_participants": {"analyzer": "czech", "type": "text"},
+                "our_participants": {"analyzer": "czech", "type": "text"},
+                "provided_benefit": {"analyzer": "czech", "type": "text"},
+                "published": {"type": "date"},
+                "received_benefit": {"analyzer": "czech", "type": "text"},
+                "title": {"analyzer": "czech", "type": "text"},
             }
         },
-        'session': {
-            'properties': {
-                'expiration': {
-                    'type': 'integer'
-                },
-                'user_id': {
-                    'type': 'keyword'
-                }
+        "session": {
+            "properties": {
+                "expiration": {"type": "integer"},
+                "user_id": {"type": "keyword"},
             }
         },
-        'user': {
-            'properties': {
-                'email': {
-                    'type': 'keyword'
-                },
-                'extra': {
-                    'type': 'object'
-                },
-                'name': {
-                    'analyzer': 'czech',
-                    'type': 'text'
-                },
-                'openid_uid': {
-                    'type': 'keyword'
-                }
+        "user": {
+            "properties": {
+                "email": {"type": "keyword"},
+                "extra": {"type": "object"},
+                "name": {"analyzer": "czech", "type": "text"},
+                "openid_uid": {"type": "keyword"},
             }
-        }
+        },
     }
 }
diff --git a/tests/snapshots/snap_test_middleware.py b/tests/snapshots/snap_test_middleware.py
index 2be80f56b2e39b8ef8bb4d16440d117633067ad3..a69726798d676b82f9e1ad0f177f6214a0d386ea 100644
--- a/tests/snapshots/snap_test_middleware.py
+++ b/tests/snapshots/snap_test_middleware.py
@@ -7,18 +7,8 @@ from snapshottest import Snapshot
 
 snapshots = Snapshot()
 
-snapshots['test_wrong_header 1'] = {
-    'errors': [
-        {
-            'message': 'Wrong Authorization header. Expected: "Bearer <token>"'
-        }
-    ]
+snapshots["test_wrong_header 1"] = {
+    "errors": [{"message": 'Wrong Authorization header. Expected: "Bearer <token>"'}]
 }
 
-snapshots['test_invalid_token 1'] = {
-    'errors': [
-        {
-            'message': 'Invalid Token.'
-        }
-    ]
-}
+snapshots["test_invalid_token 1"] = {"errors": [{"message": "Invalid Token."}]}
diff --git a/tests/snapshots/snap_test_models.py b/tests/snapshots/snap_test_models.py
index 61f5a0a38292a80edc46aa69a4e27d7342a62a3f..c957574f7d54a72319c1124d198b9f945038b44e 100644
--- a/tests/snapshots/snap_test_models.py
+++ b/tests/snapshots/snap_test_models.py
@@ -7,6 +7,6 @@ from snapshottest import Snapshot, GenericRepr
 
 snapshots = Snapshot()
 
-snapshots['test_report_is_saved_in_elasticsearch 1'] = [
+snapshots["test_report_is_saved_in_elasticsearch 1"] = [
     GenericRepr("ReportDoc(index='report_ded_test', doc_type='report_doc', id='2')")
 ]
diff --git a/tests/test_auth.py b/tests/test_auth.py
index 580bcf807c08a23d34346ba608f186b3993d5429..2373708bd90c0034f02897d01a39c4921afc32f5 100644
--- a/tests/test_auth.py
+++ b/tests/test_auth.py
@@ -3,31 +3,30 @@ import time
 import jwt
 import pytest
 
-from openlobby.core.auth import (
-    create_access_token,
-    parse_access_token,
-)
+from openlobby.core.auth import create_access_token, parse_access_token
 
 
 def test_create_access_token():
-    username = 'idkfa'
+    username = "idkfa"
     token = create_access_token(username)
-    payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
+    payload = jwt.decode(
+        token, settings.SECRET_KEY, algorithms=[settings.JWT_ALGORITHM]
+    )
     assert isinstance(token, str)
-    assert payload['sub'] == username
+    assert payload["sub"] == username
     expected_expiration = int(time.time() + settings.SESSION_EXPIRATION)
-    assert expected_expiration <= payload['exp'] <= expected_expiration + 1
+    assert expected_expiration <= payload["exp"] <= expected_expiration + 1
 
 
 def test_parse_access_token():
-    username = 'iddqd'
+    username = "iddqd"
     token = create_access_token(username)
     result = parse_access_token(token)
     assert result == username
 
 
 def test_parse_access_token__expired():
-    username = 'idfa'
+    username = "idfa"
     expiration = int(time.time() - 1)
     token = create_access_token(username, expiration)
     with pytest.raises(jwt.ExpiredSignatureError):
diff --git a/tests/test_middleware.py b/tests/test_middleware.py
index d599f7413bc149b2c0ac283c2af7d252833e68ea..45973d7ad43f67d9fe1ad30380f51fdb7f199544 100644
--- a/tests/test_middleware.py
+++ b/tests/test_middleware.py
@@ -18,22 +18,26 @@ def test_no_auth_header():
     middleware = TokenAuthMiddleware(lambda r: r)
     response = middleware(request)
 
-    request.META.get.assert_called_once_with('HTTP_AUTHORIZATION')
+    request.META.get.assert_called_once_with("HTTP_AUTHORIZATION")
     assert response == request
     assert response.user is None
 
 
 def test_authorized_user():
-    user = User.objects.create(username='wolfe', first_name='Winston',
-        last_name='Wolfe', email='winston@wolfe.com')
+    user = User.objects.create(
+        username="wolfe",
+        first_name="Winston",
+        last_name="Wolfe",
+        email="winston@wolfe.com",
+    )
     request = Mock()
     request.user = None
-    request.META.get.return_value = 'Bearer {}'.format(create_access_token('wolfe'))
+    request.META.get.return_value = "Bearer {}".format(create_access_token("wolfe"))
 
     middleware = TokenAuthMiddleware(lambda r: r)
     response = middleware(request)
 
-    request.META.get.assert_called_once_with('HTTP_AUTHORIZATION')
+    request.META.get.assert_called_once_with("HTTP_AUTHORIZATION")
     assert response == request
     assert response.user == user
 
@@ -41,39 +45,49 @@ def test_authorized_user():
 def test_wrong_header(snapshot):
     request = Mock()
     request.user = None
-    request.META.get.return_value = 'WRONG {}'.format(create_access_token('unknown'))
+    request.META.get.return_value = "WRONG {}".format(create_access_token("unknown"))
 
     middleware = TokenAuthMiddleware(lambda r: r)
     response = middleware(request)
 
-    request.META.get.assert_called_once_with('HTTP_AUTHORIZATION')
+    request.META.get.assert_called_once_with("HTTP_AUTHORIZATION")
     assert response.status_code == 400
-    as_str = response.content.decode() if hasattr(response.content, 'decode') else response.content
+    as_str = (
+        response.content.decode()
+        if hasattr(response.content, "decode")
+        else response.content
+    )
     snapshot.assert_match(json.loads(as_str))
 
 
 def test_invalid_token(snapshot):
     request = Mock()
     request.user = None
-    request.META.get.return_value = 'Bearer XXX{}'.format(create_access_token('unknown'))
+    request.META.get.return_value = "Bearer XXX{}".format(
+        create_access_token("unknown")
+    )
 
     middleware = TokenAuthMiddleware(lambda r: r)
     response = middleware(request)
 
-    request.META.get.assert_called_once_with('HTTP_AUTHORIZATION')
+    request.META.get.assert_called_once_with("HTTP_AUTHORIZATION")
     assert response.status_code == 401
-    as_str = response.content.decode() if hasattr(response.content,'decode') else response.content
+    as_str = (
+        response.content.decode()
+        if hasattr(response.content, "decode")
+        else response.content
+    )
     snapshot.assert_match(json.loads(as_str))
 
 
 def test_unknown_user(snapshot):
     request = Mock()
     request.user = None
-    request.META.get.return_value = 'Bearer {}'.format(create_access_token('unknown'))
+    request.META.get.return_value = "Bearer {}".format(create_access_token("unknown"))
 
     middleware = TokenAuthMiddleware(lambda r: r)
     response = middleware(request)
 
-    request.META.get.assert_called_once_with('HTTP_AUTHORIZATION')
+    request.META.get.assert_called_once_with("HTTP_AUTHORIZATION")
     assert response == request
     assert response.user is None
diff --git a/tests/test_models.py b/tests/test_models.py
index 80e382a634e2b929e4c7a7ec5912bd2d1cee682d..748ab929f347080f0da3483846097b21e54513c9 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -3,17 +3,20 @@ from unittest.mock import patch
 import arrow
 import pytest
 from django.conf import settings
-from openlobby.core.api.schema import AUTHOR_SORT_LAST_NAME_ID, AUTHOR_SORT_TOTAL_REPORTS_ID
+from openlobby.core.api.schema import (
+    AUTHOR_SORT_LAST_NAME_ID,
+    AUTHOR_SORT_TOTAL_REPORTS_ID,
+)
 from openlobby.core.documents import ReportDoc
 from openlobby.core.models import Report, User, OpenIdClient, LoginAttempt
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
 def test_report__marks_user_as_author_on_save():
     author = User.objects.create(id=1, is_author=False)
     date = arrow.get(2018, 1, 1).datetime
-    Report.objects.create(author=author, date=date, body='Lorem ipsum.')
+    Report.objects.create(author=author, date=date, body="Lorem ipsum.")
     user = User.objects.get(id=1)
     assert user.is_author
 
@@ -21,7 +24,7 @@ def test_report__marks_user_as_author_on_save():
 def test_report__marks_user_as_author_on_save__not_if_draft():
     author = User.objects.create(id=1, is_author=False)
     date = arrow.get(2018, 1, 1).datetime
-    Report.objects.create(author=author, is_draft=True, date=date, body='Lorem ipsum.')
+    Report.objects.create(author=author, is_draft=True, date=date, body="Lorem ipsum.")
     user = User.objects.get(id=1)
     assert not user.is_author
 
@@ -35,29 +38,29 @@ def test_report__is_saved_in_elasticsearch():
         author=author,
         date=date,
         published=published,
-        title='It happened',
-        body='Lorem ipsum.',
-        received_benefit='coffee',
-        provided_benefit='tea',
-        our_participants='me',
-        other_participants='them',
-        extra={'a': 3},
+        title="It happened",
+        body="Lorem ipsum.",
+        received_benefit="coffee",
+        provided_benefit="tea",
+        our_participants="me",
+        other_participants="them",
+        extra={"a": 3},
         is_draft=False,
     )
     docs = list(ReportDoc.search())
     assert len(docs) == 1
     doc = docs[0]
-    assert doc.meta.id == '3'
+    assert doc.meta.id == "3"
     assert doc.author_id == 6
     assert doc.date == date
     assert doc.published == published
-    assert doc.title == 'It happened'
-    assert doc.body == 'Lorem ipsum.'
-    assert doc.received_benefit == 'coffee'
-    assert doc.provided_benefit == 'tea'
-    assert doc.our_participants == 'me'
-    assert doc.other_participants == 'them'
-    assert doc.extra == {'a': 3}
+    assert doc.title == "It happened"
+    assert doc.body == "Lorem ipsum."
+    assert doc.received_benefit == "coffee"
+    assert doc.provided_benefit == "tea"
+    assert doc.our_participants == "me"
+    assert doc.other_participants == "them"
+    assert doc.extra == {"a": 3}
     assert not doc.is_draft
 
 
@@ -65,95 +68,144 @@ def test_report__save_works_with_no_extra():
     author = User.objects.create(id=6)
     date = arrow.get(2018, 1, 1).datetime
     Report.objects.create(
-        id=7,
-        author=author,
-        date=date,
-        published=date,
-        body='Lorem ipsum.',
+        id=7, author=author, date=date, published=date, body="Lorem ipsum."
     )
     docs = list(ReportDoc.search())
     assert len(docs) == 1
     doc = docs[0]
-    assert doc.meta.id == '7'
+    assert doc.meta.id == "7"
     assert doc.extra is None
 
 
 def test_login_attempt__default_expiration():
-    client = OpenIdClient.objects.create(name='a', client_id='b', client_secret='c')
-    with patch('openlobby.core.models.time.time', return_value=10000):
-        attempt = LoginAttempt.objects.create(openid_client=client, state='foo',
-                                              app_redirect_uri='http://openlobby/app')
+    client = OpenIdClient.objects.create(name="a", client_id="b", client_secret="c")
+    with patch("openlobby.core.models.time.time", return_value=10000):
+        attempt = LoginAttempt.objects.create(
+            openid_client=client, state="foo", app_redirect_uri="http://openlobby/app"
+        )
     assert attempt.expiration == 10000 + settings.LOGIN_ATTEMPT_EXPIRATION
 
 
 def test_user__no_name_collision():
-    User.objects.create(username='a', is_author=True, first_name='Ryan', last_name='Gosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='Reynolds')
-    assert User.objects.get(username='a').has_colliding_name is False
-    assert User.objects.get(username='b').has_colliding_name is False
+    User.objects.create(
+        username="a", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="Reynolds"
+    )
+    assert User.objects.get(username="a").has_colliding_name is False
+    assert User.objects.get(username="b").has_colliding_name is False
 
 
 def test_user__name_collision():
-    User.objects.create(username='a', is_author=True, first_name='Ryan', last_name='Gosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='Gosling')
-    assert User.objects.get(username='a').has_colliding_name is True
-    assert User.objects.get(username='b').has_colliding_name is True
+    User.objects.create(
+        username="a", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
+    assert User.objects.get(username="a").has_colliding_name is True
+    assert User.objects.get(username="b").has_colliding_name is True
 
 
 def test_user__name_collision_affects_only_authors():
-    User.objects.create(username='a', is_author=False, first_name='Ryan', last_name='Gosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='Gosling')
-    User.objects.create(username='c', is_author=False, first_name='Ryan', last_name='Gosling')
-    assert User.objects.get(username='a').has_colliding_name is False
-    assert User.objects.get(username='b').has_colliding_name is False
-    assert User.objects.get(username='c').has_colliding_name is False
-    User.objects.create(username='d', is_author=True, first_name='Ryan', last_name='Gosling')
-    assert User.objects.get(username='a').has_colliding_name is False
-    assert User.objects.get(username='b').has_colliding_name is True
-    assert User.objects.get(username='c').has_colliding_name is False
-    assert User.objects.get(username='d').has_colliding_name is True
+    User.objects.create(
+        username="a", is_author=False, first_name="Ryan", last_name="Gosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
+    User.objects.create(
+        username="c", is_author=False, first_name="Ryan", last_name="Gosling"
+    )
+    assert User.objects.get(username="a").has_colliding_name is False
+    assert User.objects.get(username="b").has_colliding_name is False
+    assert User.objects.get(username="c").has_colliding_name is False
+    User.objects.create(
+        username="d", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
+    assert User.objects.get(username="a").has_colliding_name is False
+    assert User.objects.get(username="b").has_colliding_name is True
+    assert User.objects.get(username="c").has_colliding_name is False
+    assert User.objects.get(username="d").has_colliding_name is True
 
 
 def test_user__name_collision_excludes_self_on_update():
-    u = User.objects.create(username='a', is_author=True, first_name='Ryan', last_name='Gosling')
+    u = User.objects.create(
+        username="a", is_author=True, first_name="Ryan", last_name="Gosling"
+    )
     u.save()
-    assert User.objects.get(username='a').has_colliding_name is False
+    assert User.objects.get(username="a").has_colliding_name is False
 
 
 def test_user__sorted_default():
-    User.objects.create(username='a', is_author=False, first_name='Ryan', last_name='AGosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='BGosling')
-    User.objects.create(username='c', is_author=False, first_name='Ryan', last_name='CGosling')
-    assert User.objects.sorted()[0].username == 'a'
+    User.objects.create(
+        username="a", is_author=False, first_name="Ryan", last_name="AGosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="BGosling"
+    )
+    User.objects.create(
+        username="c", is_author=False, first_name="Ryan", last_name="CGosling"
+    )
+    assert User.objects.sorted()[0].username == "a"
 
 
 def test_user__sorted_default_reversed():
-    User.objects.create(username='a', is_author=False, first_name='Ryan', last_name='AGosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='BGosling')
-    User.objects.create(username='c', is_author=False, first_name='Ryan', last_name='CGosling')
-    assert User.objects.sorted(reversed=True)[0].username == 'c'
+    User.objects.create(
+        username="a", is_author=False, first_name="Ryan", last_name="AGosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="BGosling"
+    )
+    User.objects.create(
+        username="c", is_author=False, first_name="Ryan", last_name="CGosling"
+    )
+    assert User.objects.sorted(reversed=True)[0].username == "c"
 
 
 def test_user__sorted_last_name():
-    User.objects.create(username='a', is_author=False, first_name='Ryan', last_name='AGosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='BGosling')
-    User.objects.create(username='c', is_author=False, first_name='Ryan', last_name='CGosling')
-    assert User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID)[0].username == 'a'
-    assert User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID, reversed=False)[0].username == 'a'
-    assert User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID, reversed=True)[0].username == 'c'
+    User.objects.create(
+        username="a", is_author=False, first_name="Ryan", last_name="AGosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="BGosling"
+    )
+    User.objects.create(
+        username="c", is_author=False, first_name="Ryan", last_name="CGosling"
+    )
+    assert User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID)[0].username == "a"
+    assert (
+        User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID, reversed=False)[0].username
+        == "a"
+    )
+    assert (
+        User.objects.sorted(sort=AUTHOR_SORT_LAST_NAME_ID, reversed=True)[0].username
+        == "c"
+    )
 
 
 def test_user__sorted_total_reports():
-    author = User.objects.create(username='a', is_author=True, first_name='Ryan', last_name='AGosling')
-    User.objects.create(username='b', is_author=True, first_name='Ryan', last_name='BGosling')
+    author = User.objects.create(
+        username="a", is_author=True, first_name="Ryan", last_name="AGosling"
+    )
+    User.objects.create(
+        username="b", is_author=True, first_name="Ryan", last_name="BGosling"
+    )
     date = arrow.get(2018, 1, 1).datetime
     Report.objects.create(
-        id=7,
-        author=author,
-        date=date,
-        published=date,
-        body='Lorem ipsum.',
+        id=7, author=author, date=date, published=date, body="Lorem ipsum."
+    )
+    assert User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID)[0].username == "a"
+    assert (
+        User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID, reversed=False)[
+            0
+        ].username
+        == "a"
+    )
+    assert (
+        User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID, reversed=True)[
+            0
+        ].username
+        == "b"
     )
-    assert User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID)[0].username == 'a'
-    assert User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID, reversed=False)[0].username == 'a'
-    assert User.objects.sorted(sort=AUTHOR_SORT_TOTAL_REPORTS_ID, reversed=True)[0].username == 'b'
diff --git a/tests/test_paginator.py b/tests/test_paginator.py
index 8a8d08c8fb823235a518ef05ddf7c8c27c056743..c859a6ca595ddcbf4c003fbc593f6a8b0e5bf3cb 100644
--- a/tests/test_paginator.py
+++ b/tests/test_paginator.py
@@ -9,20 +9,12 @@ from openlobby.core.api.paginator import (
 )
 
 
-@pytest.mark.parametrize('num, cursor', [
-    (5, 'NQ=='),
-    (777, 'Nzc3'),
-    (12, 'MTI='),
-])
+@pytest.mark.parametrize("num, cursor", [(5, "NQ=="), (777, "Nzc3"), (12, "MTI=")])
 def test_encode_cursor(num, cursor):
     assert encode_cursor(num) == cursor
 
 
-@pytest.mark.parametrize('num, cursor', [
-    (8, 'OA=='),
-    (123, 'MTIz'),
-    (65, 'NjU='),
-])
+@pytest.mark.parametrize("num, cursor", [(8, "OA=="), (123, "MTIz"), (65, "NjU=")])
 def test_decode_cursor(num, cursor):
     assert decode_cursor(cursor) == num
 
@@ -44,15 +36,18 @@ def test_paginator__custom_per_page():
     assert paginator.slice_to == 5
 
 
-@pytest.mark.parametrize('kw, slice_from, slice_to', [
-    ({'first': 15}, 0, 15),
-    ({'first': 5, 'after': encode_cursor(3)}, 3, 8),
-    ({'last': 8, 'before': encode_cursor(20)}, 11, 19),
-    # overflow of slice_from
-    ({'last': 100, 'before': encode_cursor(42)}, 0, 41),
-    # preffer first before last if both provided
-    ({'first': 20, 'last': 4}, 0, 20),
-])
+@pytest.mark.parametrize(
+    "kw, slice_from, slice_to",
+    [
+        ({"first": 15}, 0, 15),
+        ({"first": 5, "after": encode_cursor(3)}, 3, 8),
+        ({"last": 8, "before": encode_cursor(20)}, 11, 19),
+        # overflow of slice_from
+        ({"last": 100, "before": encode_cursor(42)}, 0, 41),
+        # preffer first before last if both provided
+        ({"first": 20, "last": 4}, 0, 20),
+    ],
+)
 def test_paginator__input_combinations(kw, slice_from, slice_to):
     paginator = Paginator(**kw)
     assert paginator.slice_from == slice_from
@@ -64,24 +59,27 @@ def test_paginator__last_without_before():
         Paginator(last=1)
 
 
-@pytest.mark.parametrize('kw, total, previous, next, start, end', [
-    ({}, 10, False, False, 1, 10),
-    ({}, 15, False, True, 1, 10),
-    ({}, 5, False, False, 1, 5),
-    ({'first': 1}, 10, False, True, 1, 1),
-    ({'first': 6}, 10, False, True, 1, 6),
-    ({'first': 6}, 4, False, False, 1, 4),
-    ({'first': 6}, 6, False, False, 1, 6),
-    ({'first': 3, 'after': encode_cursor(7)}, 20, True, True, 8, 10),
-    ({'first': 3, 'after': encode_cursor(17)}, 20, True, False, 18, 20),
-    ({'first': 5, 'after': encode_cursor(17)}, 20, True, False, 18, 20),
-    ({'last': 4, 'before': encode_cursor(10)}, 20, True, True, 6, 9),
-    ({'last': 4, 'before': encode_cursor(5)}, 20, False, True, 1, 4),
-    ({'last': 4, 'before': encode_cursor(3)}, 20, False, True, 1, 2),
-    # out of bounds
-    ({'first': 3, 'after': encode_cursor(10)}, 10, False, False, None, None),
-    ({'last': 3, 'before': encode_cursor(1)}, 10, False, False, None, None),
-])
+@pytest.mark.parametrize(
+    "kw, total, previous, next, start, end",
+    [
+        ({}, 10, False, False, 1, 10),
+        ({}, 15, False, True, 1, 10),
+        ({}, 5, False, False, 1, 5),
+        ({"first": 1}, 10, False, True, 1, 1),
+        ({"first": 6}, 10, False, True, 1, 6),
+        ({"first": 6}, 4, False, False, 1, 4),
+        ({"first": 6}, 6, False, False, 1, 6),
+        ({"first": 3, "after": encode_cursor(7)}, 20, True, True, 8, 10),
+        ({"first": 3, "after": encode_cursor(17)}, 20, True, False, 18, 20),
+        ({"first": 5, "after": encode_cursor(17)}, 20, True, False, 18, 20),
+        ({"last": 4, "before": encode_cursor(10)}, 20, True, True, 6, 9),
+        ({"last": 4, "before": encode_cursor(5)}, 20, False, True, 1, 4),
+        ({"last": 4, "before": encode_cursor(3)}, 20, False, True, 1, 2),
+        # out of bounds
+        ({"first": 3, "after": encode_cursor(10)}, 10, False, False, None, None),
+        ({"last": 3, "before": encode_cursor(1)}, 10, False, False, None, None),
+    ],
+)
 def test_paginator__get_page_info(kw, total, previous, next, start, end):
     paginator = Paginator(**kw)
     page_info = paginator.get_page_info(total)
@@ -91,11 +89,14 @@ def test_paginator__get_page_info(kw, total, previous, next, start, end):
     assert page_info.end_cursor == end if end is None else encode_cursor(end)
 
 
-@pytest.mark.parametrize('kw, num, cursor', [
-    ({}, 3, encode_cursor(3)),
-    ({'first': 6, 'after': encode_cursor(1)}, 3, encode_cursor(4)),
-    ({'last': 6, 'before': encode_cursor(11)}, 3, encode_cursor(7)),
-])
+@pytest.mark.parametrize(
+    "kw, num, cursor",
+    [
+        ({}, 3, encode_cursor(3)),
+        ({"first": 6, "after": encode_cursor(1)}, 3, encode_cursor(4)),
+        ({"last": 6, "before": encode_cursor(11)}, 3, encode_cursor(7)),
+    ],
+)
 def test_paginator__get_edge_cursor(kw, num, cursor):
     paginator = Paginator(**kw)
     assert paginator.get_edge_cursor(num) == cursor
diff --git a/tests/test_sanitizers.py b/tests/test_sanitizers.py
index 74ed2722145b8b924253ebe6046baacd866eac90..08162d31efa6f0b662b598c05b6f67850fecb228 100644
--- a/tests/test_sanitizers.py
+++ b/tests/test_sanitizers.py
@@ -3,24 +3,30 @@ import pytest
 from openlobby.core.api.sanitizers import strip_all_tags, extract_text
 
 
-@pytest.mark.parametrize('input, text', [
-    ('foo', 'foo'),
-    ('has multiple words', 'has multiple words'),
-    ('has <b>some</b> tags', 'has some tags'),
-    ("<IMG SRC=j&#X41vascript:alert('test2')>", ''),
-])
+@pytest.mark.parametrize(
+    "input, text",
+    [
+        ("foo", "foo"),
+        ("has multiple words", "has multiple words"),
+        ("has <b>some</b> tags", "has some tags"),
+        ("<IMG SRC=j&#X41vascript:alert('test2')>", ""),
+    ],
+)
 def test_strip_all_tags(input, text):
     assert strip_all_tags(input) == text
 
 
-@pytest.mark.parametrize('input, text', [
-    ('foo', 'foo'),
-    ('has multiple words', 'has multiple words'),
-    ('has <b>some</b> tags', 'has some tags'),
-    ('x" onload="alert()"', 'x onload alert'),
-    ("'; drop database; x='y", 'drop database x y'),
-    ("<IMG SRC=j&#X41vascript:alert('test2')>", ''),
-    ('=/*-+.', ''),
-])
+@pytest.mark.parametrize(
+    "input, text",
+    [
+        ("foo", "foo"),
+        ("has multiple words", "has multiple words"),
+        ("has <b>some</b> tags", "has some tags"),
+        ('x" onload="alert()"', "x onload alert"),
+        ("'; drop database; x='y", "drop database x y"),
+        ("<IMG SRC=j&#X41vascript:alert('test2')>", ""),
+        ("=/*-+.", ""),
+    ],
+)
 def test_extract_text(input, text):
     assert extract_text(input) == text
diff --git a/tests/test_search.py b/tests/test_search.py
index 5e8d6d0495d6c7a504626e67a895fd985a17e67e..27c77702829a18631501ee5460b4a3932ffe8361 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -6,15 +6,13 @@ from openlobby.core.search import query_reports, reports_by_author
 from .dummy import prepare_reports
 
 
-pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures('django_es')]
+pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")]
 
 
-@pytest.mark.parametrize('query, expected_ids', [
-    ('', [3, 2, 1]),
-    ('sauron', [3, 2]),
-    ('towers', [2]),
-    ('Aragorn Gandalf', [3, 1]),
-])
+@pytest.mark.parametrize(
+    "query, expected_ids",
+    [("", [3, 2, 1]), ("sauron", [3, 2]), ("towers", [2]), ("Aragorn Gandalf", [3, 1])],
+)
 def test_query_reports(query, expected_ids):
     prepare_reports()
     paginator = Paginator()
@@ -25,20 +23,19 @@ def test_query_reports(query, expected_ids):
 def test_query_reports__highlight():
     prepare_reports()
     paginator = Paginator()
-    query = 'King'
+    query = "King"
     response = query_reports(query, paginator, highlight=True)
     doc = response.hits[0]
-    assert '<mark>King</mark>' in doc.meta.highlight.title[0]
-    assert '<mark>King</mark>' in doc.meta.highlight.body[0]
+    assert "<mark>King</mark>" in doc.meta.highlight.title[0]
+    assert "<mark>King</mark>" in doc.meta.highlight.body[0]
 
 
-@pytest.mark.parametrize('first, after, expected_ids', [
-    (2, None, [3, 2]),
-    (2, encode_cursor(1), [2, 1]),
-])
+@pytest.mark.parametrize(
+    "first, after, expected_ids", [(2, None, [3, 2]), (2, encode_cursor(1), [2, 1])]
+)
 def test_query_reports__pagination(first, after, expected_ids):
     prepare_reports()
-    query = ''
+    query = ""
     paginator = Paginator(first=first, after=after)
     response = query_reports(query, paginator)
     assert expected_ids == [int(r.meta.id) for r in response]
@@ -52,10 +49,9 @@ def test_reports_by_author():
     assert [3, 1] == [int(r.meta.id) for r in response]
 
 
-@pytest.mark.parametrize('first, after, expected_ids', [
-    (1, None, [3]),
-    (1, encode_cursor(1), [1]),
-])
+@pytest.mark.parametrize(
+    "first, after, expected_ids", [(1, None, [3]), (1, encode_cursor(1), [1])]
+)
 def test_reports_by_author__pagination(first, after, expected_ids):
     prepare_reports()
     author_id = 1
diff --git a/tests/test_views.py b/tests/test_views.py
index b67547d90cc05e2d2e095b1910bfce1cbdc4d2a0..7eb86f996f9515a2470ba94c8420c33969edb122 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -12,39 +12,47 @@ pytestmark = pytest.mark.django_db
 
 
 def test_login_redirect__new_user(client, issuer):
-    state = 'IDDQD'
-    sub = 'IDKFA'
-    openid_uid = 'elon.musk@openid'
-    first_name = 'Elon'
-    last_name = 'Musk'
-    email = 'elon.musk@tesla.com'
-    app_redirect_uri = 'http://doom.is.legend'
+    state = "IDDQD"
+    sub = "IDKFA"
+    openid_uid = "elon.musk@openid"
+    first_name = "Elon"
+    last_name = "Musk"
+    email = "elon.musk@tesla.com"
+    app_redirect_uri = "http://doom.is.legend"
 
     oc = register_client(issuer)
-    oid_client = OpenIdClient.objects.create(name='Test', issuer=issuer,
-        client_id=oc.client_id, client_secret=oc.client_secret)
-    LoginAttempt.objects.create(openid_client=oid_client, state=state,
-        app_redirect_uri=app_redirect_uri, openid_uid=openid_uid)
+    oid_client = OpenIdClient.objects.create(
+        name="Test",
+        issuer=issuer,
+        client_id=oc.client_id,
+        client_secret=oc.client_secret,
+    )
+    LoginAttempt.objects.create(
+        openid_client=oid_client,
+        state=state,
+        app_redirect_uri=app_redirect_uri,
+        openid_uid=openid_uid,
+    )
 
     # we are not testing real redirect url params, so we mock communication with
     # OpenID Provider
     user_info = {
-        'sub': sub,
-        'given_name': first_name,
-        'family_name': last_name,
-        'email': email,
+        "sub": sub,
+        "given_name": first_name,
+        "family_name": last_name,
+        "email": email,
     }
-    with patch('openlobby.core.views.get_user_info', return_value=user_info) as mock:
-        response = client.get(reverse('login-redirect'), {'state': state})
+    with patch("openlobby.core.views.get_user_info", return_value=user_info) as mock:
+        response = client.get(reverse("login-redirect"), {"state": state})
         m_client, m_query_string = mock.call_args[0]
         assert m_client.client_id == oc.client_id
-        assert m_query_string == 'state={}'.format(state)
+        assert m_query_string == "state={}".format(state)
 
     assert response.status_code == 302
-    url, query_string = response.url.split('?')
+    url, query_string = response.url.split("?")
     qs = urllib.parse.parse_qs(query_string)
     assert url == app_redirect_uri
-    assert sub == parse_access_token(qs['token'][0])
+    assert sub == parse_access_token(qs["token"][0])
 
     user = User.objects.get()
     assert user.username == sub
@@ -55,42 +63,55 @@ def test_login_redirect__new_user(client, issuer):
 
 
 def test_login_redirect__existing_user(client, issuer):
-    state = 'IDDQD'
-    sub = 'IDKFA'
-    openid_uid = 'elon.musk@openid'
-    first_name = 'Elon'
-    last_name = 'Musk'
-    email = 'elon.musk@tesla.com'
-    app_redirect_uri = 'http://doom.is.legend'
+    state = "IDDQD"
+    sub = "IDKFA"
+    openid_uid = "elon.musk@openid"
+    first_name = "Elon"
+    last_name = "Musk"
+    email = "elon.musk@tesla.com"
+    app_redirect_uri = "http://doom.is.legend"
 
     oc = register_client(issuer)
-    oid_client = OpenIdClient.objects.create(name='Test', issuer=issuer,
-        client_id=oc.client_id, client_secret=oc.client_secret)
-    LoginAttempt.objects.create(openid_client=oid_client, state=state,
-        app_redirect_uri=app_redirect_uri, openid_uid=openid_uid)
-    User.objects.create(username=sub, first_name=first_name, last_name=last_name,
-        email=email, openid_uid=openid_uid)
+    oid_client = OpenIdClient.objects.create(
+        name="Test",
+        issuer=issuer,
+        client_id=oc.client_id,
+        client_secret=oc.client_secret,
+    )
+    LoginAttempt.objects.create(
+        openid_client=oid_client,
+        state=state,
+        app_redirect_uri=app_redirect_uri,
+        openid_uid=openid_uid,
+    )
+    User.objects.create(
+        username=sub,
+        first_name=first_name,
+        last_name=last_name,
+        email=email,
+        openid_uid=openid_uid,
+    )
 
     # we are not testing real redirect url params, so we mock communication with
     # OpenID Provider
     user_info = {
-        'sub': sub,
+        "sub": sub,
         # return different details
-        'given_name': 'Elons',
-        'family_name': 'Mustache',
-        'email': 'elons.mustache@spacex.com',
+        "given_name": "Elons",
+        "family_name": "Mustache",
+        "email": "elons.mustache@spacex.com",
     }
-    with patch('openlobby.core.views.get_user_info', return_value=user_info) as mock:
-        response = client.get(reverse('login-redirect'), {'state': state})
+    with patch("openlobby.core.views.get_user_info", return_value=user_info) as mock:
+        response = client.get(reverse("login-redirect"), {"state": state})
         m_client, m_query_string = mock.call_args[0]
         assert m_client.client_id == oc.client_id
-        assert m_query_string == 'state={}'.format(state)
+        assert m_query_string == "state={}".format(state)
 
     assert response.status_code == 302
-    url, query_string = response.url.split('?')
+    url, query_string = response.url.split("?")
     qs = urllib.parse.parse_qs(query_string)
     assert url == app_redirect_uri
-    assert sub == parse_access_token(qs['token'][0])
+    assert sub == parse_access_token(qs["token"][0])
 
     # check there is still just one user, who's details are not updated
     user = User.objects.get()
diff --git a/tests/utils.py b/tests/utils.py
index 2f03456bd4bd7f729652a852ceb95cc4390c5b3d..e836d9db592b058b87e65a4d0ed613d8f575bf70 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -4,14 +4,17 @@ from openlobby.core.auth import create_access_token
 
 
 def call_api(client, query, input=None, username=None):
-    variables = json.dumps({'input': input or {}})
+    variables = json.dumps({"input": input or {}})
     if username is None:
-        res = client.post('/graphql', {'query': query, 'variables': variables})
+        res = client.post("/graphql", {"query": query, "variables": variables})
     else:
         token = create_access_token(username)
-        auth_header = 'Bearer {}'.format(token)
-        res = client.post('/graphql', {'query': query, 'variables': variables},
-            HTTP_AUTHORIZATION=auth_header)
+        auth_header = "Bearer {}".format(token)
+        res = client.post(
+            "/graphql",
+            {"query": query, "variables": variables},
+            HTTP_AUTHORIZATION=auth_header,
+        )
     return res.json()
 
 
@@ -19,7 +22,7 @@ def strip_value(data, *path):
     element = path[0]
     value = data.get(element)
     if len(path) == 1:
-        data[element] = '__STRIPPED__'
+        data[element] = "__STRIPPED__"
         return value
     else:
         return strip_value(value, *path[1:])