From c2d0e0f9d82e4115cb9508c82ca65059295adedf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 13 Dec 2019 15:58:24 +0100
Subject: [PATCH 1/4] misc: black (#29209)

---
 .../sync_desks_timeperiod_exceptions.py       |   3 +-
 chrono/agendas/migrations/0001_initial.py     |  14 +-
 chrono/agendas/migrations/0002_event.py       |  11 +-
 chrono/agendas/migrations/0003_booking.py     |  10 +-
 .../0004_booking_cancellation_datetime.py     |   2 +-
 chrono/agendas/migrations/0005_event_label.py |   8 +-
 .../migrations/0006_auto_20160707_1357.py     |  17 +-
 .../migrations/0007_auto_20160722_1135.py     |   4 +-
 .../migrations/0008_auto_20160910_1319.py     |  41 +-
 .../migrations/0010_auto_20160918_1250.py     |  23 +-
 .../migrations/0013_auto_20161028_1603.py     |   4 +-
 .../0014_booking_primary_booking.py           |   7 +-
 .../migrations/0015_auto_20170628_1137.py     |  12 +-
 chrono/agendas/migrations/0016_desk.py        |   9 +-
 .../migrations/0017_timeperiod_desk.py        |   8 +-
 chrono/agendas/migrations/0018_event_desk.py  |   5 +-
 .../migrations/0019_timeperiodexception.py    |  14 +-
 .../migrations/0020_auto_20171102_1021.py     |   7 +-
 .../migrations/0021_auto_20171126_1330.py     |  14 +-
 .../migrations/0022_auto_20171202_1828.py     |   4 +-
 .../migrations/0023_auto_20171202_1835.py     |   4 +-
 .../migrations/0024_auto_20180426_1127.py     |   5 +-
 .../migrations/0025_auto_20181206_1252.py     |  22 +-
 .../migrations/0027_event_description.py      |   4 +-
 chrono/agendas/migrations/0028_event_slug.py  |   4 +-
 .../migrations/0029_auto_20191106_1320.py     |   4 +-
 .../migrations/0030_auto_20191107_1200.py     |   6 +-
 .../migrations/0031_auto_20191107_1225.py     |  10 +-
 .../migrations/0032_auto_20191127_0919.py     |   9 +-
 chrono/agendas/models.py                      | 212 +++---
 chrono/api/urls.py                            |  49 +-
 chrono/api/views.py                           | 410 +++++++-----
 chrono/interval.py                            |   1 +
 chrono/manager/forms.py                       | 107 +--
 .../management/commands/export_site.py        |   4 +-
 .../management/commands/import_site.py        |  25 +-
 chrono/manager/urls.py                        | 153 +++--
 chrono/manager/views.py                       | 304 ++++++---
 chrono/manager/widgets.py                     |  46 +-
 chrono/settings.py                            |  16 +-
 chrono/urls.py                                |   9 +-
 chrono/urls_utils.py                          |   3 +-
 chrono/views.py                               |   6 +-
 chrono/wsgi.py                                |   5 +-
 tests/conftest.py                             |   3 +-
 tests/test_agendas.py                         |  85 ++-
 tests/test_api.py                             | 615 ++++++++++++------
 tests/test_api_utils.py                       |  17 +-
 tests/test_data_migrations.py                 |  44 +-
 tests/test_import_export.py                   |  33 +-
 tests/test_manager.py                         | 346 ++++++----
 tests/test_misc.py                            |   1 +
 tests/test_sso.py                             |   3 +-
 tests/test_time_periods.py                    | 162 +++--
 54 files changed, 1801 insertions(+), 1143 deletions(-)

diff --git a/chrono/agendas/management/commands/sync_desks_timeperiod_exceptions.py b/chrono/agendas/management/commands/sync_desks_timeperiod_exceptions.py
index f0f0599..7db8e90 100644
--- a/chrono/agendas/management/commands/sync_desks_timeperiod_exceptions.py
+++ b/chrono/agendas/management/commands/sync_desks_timeperiod_exceptions.py
@@ -18,9 +18,10 @@ from __future__ import print_function
 
 import sys
 
-from chrono.agendas.models import Desk, ICSError
 from django.core.management.base import BaseCommand
 
+from chrono.agendas.models import Desk, ICSError
+
 
 class Command(BaseCommand):
     help = 'Synchronize time period exceptions from desks remote ics'
diff --git a/chrono/agendas/migrations/0001_initial.py b/chrono/agendas/migrations/0001_initial.py
index f6a07cb..450e411 100644
--- a/chrono/agendas/migrations/0001_initial.py
+++ b/chrono/agendas/migrations/0001_initial.py
@@ -1,25 +1,25 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-    ]
+    dependencies = []
 
     operations = [
         migrations.CreateModel(
             name='Agenda',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('label', models.CharField(max_length=50, verbose_name='Label')),
                 ('slug', models.SlugField(verbose_name='Identifier')),
             ],
-            options={
-                'ordering': ['label'],
-            },
+            options={'ordering': ['label'],},
             bases=(models.Model,),
         ),
     ]
diff --git a/chrono/agendas/migrations/0002_event.py b/chrono/agendas/migrations/0002_event.py
index 368b50a..c9f243b 100644
--- a/chrono/agendas/migrations/0002_event.py
+++ b/chrono/agendas/migrations/0002_event.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,14 +14,15 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Event',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('start_datetime', models.DateTimeField(verbose_name='Date/time')),
                 ('places', models.PositiveIntegerField(verbose_name='Places')),
                 ('agenda', models.ForeignKey(to='agendas.Agenda', on_delete=models.CASCADE)),
             ],
-            options={
-                'ordering': ['agenda', 'start_datetime'],
-            },
+            options={'ordering': ['agenda', 'start_datetime'],},
             bases=(models.Model,),
         ),
     ]
diff --git a/chrono/agendas/migrations/0003_booking.py b/chrono/agendas/migrations/0003_booking.py
index c890aba..5ea140f 100644
--- a/chrono/agendas/migrations/0003_booking.py
+++ b/chrono/agendas/migrations/0003_booking.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import models, migrations
 import jsonfield.fields
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -15,12 +15,14 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Booking',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('extra_data', jsonfield.fields.JSONField(null=True)),
                 ('event', models.ForeignKey(to='agendas.Event', on_delete=models.CASCADE)),
             ],
-            options={
-            },
+            options={},
             bases=(models.Model,),
         ),
     ]
diff --git a/chrono/agendas/migrations/0004_booking_cancellation_datetime.py b/chrono/agendas/migrations/0004_booking_cancellation_datetime.py
index 2eac49c..d5d3fbc 100644
--- a/chrono/agendas/migrations/0004_booking_cancellation_datetime.py
+++ b/chrono/agendas/migrations/0004_booking_cancellation_datetime.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import models, migrations
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
diff --git a/chrono/agendas/migrations/0005_event_label.py b/chrono/agendas/migrations/0005_event_label.py
index 56dfe49..b6f80b4 100644
--- a/chrono/agendas/migrations/0005_event_label.py
+++ b/chrono/agendas/migrations/0005_event_label.py
@@ -14,6 +14,12 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='event',
             name='label',
-            field=models.CharField(help_text='Optional label to identify this date.', max_length=50, null=True, blank=True, verbose_name='Label'),
+            field=models.CharField(
+                help_text='Optional label to identify this date.',
+                max_length=50,
+                null=True,
+                blank=True,
+                verbose_name='Label',
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0006_auto_20160707_1357.py b/chrono/agendas/migrations/0006_auto_20160707_1357.py
index 87597e7..42a4c63 100644
--- a/chrono/agendas/migrations/0006_auto_20160707_1357.py
+++ b/chrono/agendas/migrations/0006_auto_20160707_1357.py
@@ -1,8 +1,9 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import migrations, models
 import datetime
+
+from django.db import migrations, models
 from django.utils.timezone import utc
 
 
@@ -16,19 +17,15 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='booking',
             name='creation_datetime',
-            field=models.DateTimeField(default=datetime.datetime(2016, 7, 7, 13, 57, 47, 975893, tzinfo=utc), auto_now_add=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2016, 7, 7, 13, 57, 47, 975893, tzinfo=utc), auto_now_add=True
+            ),
             preserve_default=False,
         ),
         migrations.AddField(
-            model_name='booking',
-            name='in_waiting_list',
-            field=models.BooleanField(default=False),
-        ),
-        migrations.AddField(
-            model_name='event',
-            name='full',
-            field=models.BooleanField(default=False),
+            model_name='booking', name='in_waiting_list', field=models.BooleanField(default=False),
         ),
+        migrations.AddField(model_name='event', name='full', field=models.BooleanField(default=False),),
         migrations.AddField(
             model_name='event',
             name='waiting_list_places',
diff --git a/chrono/agendas/migrations/0007_auto_20160722_1135.py b/chrono/agendas/migrations/0007_auto_20160722_1135.py
index eadaf23..5329a80 100644
--- a/chrono/agendas/migrations/0007_auto_20160722_1135.py
+++ b/chrono/agendas/migrations/0007_auto_20160722_1135.py
@@ -12,8 +12,6 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.AlterField(
-            model_name='agenda',
-            name='label',
-            field=models.CharField(max_length=100, verbose_name='Label'),
+            model_name='agenda', name='label', field=models.CharField(max_length=100, verbose_name='Label'),
         ),
     ]
diff --git a/chrono/agendas/migrations/0008_auto_20160910_1319.py b/chrono/agendas/migrations/0008_auto_20160910_1319.py
index 3ea66b3..0aa24e7 100644
--- a/chrono/agendas/migrations/0008_auto_20160910_1319.py
+++ b/chrono/agendas/migrations/0008_auto_20160910_1319.py
@@ -14,30 +14,51 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='MeetingType',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('label', models.CharField(max_length=100, verbose_name='Label')),
                 ('duration', models.IntegerField(default=30, verbose_name='Duration (in minutes)')),
             ],
-            options={
-                'ordering': ['label'],
-            },
+            options={'ordering': ['label'],},
         ),
         migrations.CreateModel(
             name='TimePeriod',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('weekday', models.IntegerField(verbose_name='Week day', choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')])),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
+                (
+                    'weekday',
+                    models.IntegerField(
+                        verbose_name='Week day',
+                        choices=[
+                            (0, 'Monday'),
+                            (1, 'Tuesday'),
+                            (2, 'Wednesday'),
+                            (3, 'Thursday'),
+                            (4, 'Friday'),
+                            (5, 'Saturday'),
+                            (6, 'Sunday'),
+                        ],
+                    ),
+                ),
                 ('start_time', models.TimeField(verbose_name='Start')),
                 ('end_time', models.TimeField(verbose_name='End')),
             ],
-            options={
-                'ordering': ['weekday', 'start_time'],
-            },
+            options={'ordering': ['weekday', 'start_time'],},
         ),
         migrations.AddField(
             model_name='agenda',
             name='kind',
-            field=models.CharField(default=b'events', max_length=20, verbose_name='Kind', choices=[(b'events', 'Events'), (b'meetings', 'Meetings')]),
+            field=models.CharField(
+                default=b'events',
+                max_length=20,
+                verbose_name='Kind',
+                choices=[(b'events', 'Events'), (b'meetings', 'Meetings')],
+            ),
         ),
         migrations.AddField(
             model_name='timeperiod',
diff --git a/chrono/agendas/migrations/0010_auto_20160918_1250.py b/chrono/agendas/migrations/0010_auto_20160918_1250.py
index d92977e..449bdba 100644
--- a/chrono/agendas/migrations/0010_auto_20160918_1250.py
+++ b/chrono/agendas/migrations/0010_auto_20160918_1250.py
@@ -13,17 +13,32 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.AlterModelOptions(
-            name='event',
-            options={'ordering': ['agenda', 'start_datetime', 'label']},
+            name='event', options={'ordering': ['agenda', 'start_datetime', 'label']},
         ),
         migrations.AddField(
             model_name='agenda',
             name='edit_role',
-            field=models.ForeignKey(related_name='+', default=None, verbose_name='Edit Role', to='auth.Group', blank=True, null=True, on_delete=models.CASCADE),
+            field=models.ForeignKey(
+                related_name='+',
+                default=None,
+                verbose_name='Edit Role',
+                to='auth.Group',
+                blank=True,
+                null=True,
+                on_delete=models.CASCADE,
+            ),
         ),
         migrations.AddField(
             model_name='agenda',
             name='view_role',
-            field=models.ForeignKey(related_name='+', default=None, verbose_name='View Role', to='auth.Group', blank=True, null=True, on_delete=models.CASCADE),
+            field=models.ForeignKey(
+                related_name='+',
+                default=None,
+                verbose_name='View Role',
+                to='auth.Group',
+                blank=True,
+                null=True,
+                on_delete=models.CASCADE,
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0013_auto_20161028_1603.py b/chrono/agendas/migrations/0013_auto_20161028_1603.py
index 456af26..8586a24 100644
--- a/chrono/agendas/migrations/0013_auto_20161028_1603.py
+++ b/chrono/agendas/migrations/0013_auto_20161028_1603.py
@@ -12,8 +12,6 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.AlterField(
-            model_name='meetingtype',
-            name='slug',
-            field=models.SlugField(verbose_name='Identifier'),
+            model_name='meetingtype', name='slug', field=models.SlugField(verbose_name='Identifier'),
         ),
     ]
diff --git a/chrono/agendas/migrations/0014_booking_primary_booking.py b/chrono/agendas/migrations/0014_booking_primary_booking.py
index 4940bb6..23fd6e2 100644
--- a/chrono/agendas/migrations/0014_booking_primary_booking.py
+++ b/chrono/agendas/migrations/0014_booking_primary_booking.py
@@ -14,6 +14,11 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='booking',
             name='primary_booking',
-            field=models.ForeignKey(related_name='secondary_booking_set', to='agendas.Booking', null=True, on_delete=models.CASCADE),
+            field=models.ForeignKey(
+                related_name='secondary_booking_set',
+                to='agendas.Booking',
+                null=True,
+                on_delete=models.CASCADE,
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0015_auto_20170628_1137.py b/chrono/agendas/migrations/0015_auto_20170628_1137.py
index fe3c410..01ba0e7 100644
--- a/chrono/agendas/migrations/0015_auto_20170628_1137.py
+++ b/chrono/agendas/migrations/0015_auto_20170628_1137.py
@@ -12,14 +12,18 @@ class Migration(migrations.Migration):
 
     operations = [
         migrations.AlterField(
-            model_name='agenda',
-            name='label',
-            field=models.CharField(max_length=150, verbose_name='Label'),
+            model_name='agenda', name='label', field=models.CharField(max_length=150, verbose_name='Label'),
         ),
         migrations.AlterField(
             model_name='event',
             name='label',
-            field=models.CharField(help_text='Optional label to identify this date.', max_length=150, null=True, verbose_name='Label', blank=True),
+            field=models.CharField(
+                help_text='Optional label to identify this date.',
+                max_length=150,
+                null=True,
+                verbose_name='Label',
+                blank=True,
+            ),
         ),
         migrations.AlterField(
             model_name='meetingtype',
diff --git a/chrono/agendas/migrations/0016_desk.py b/chrono/agendas/migrations/0016_desk.py
index 914011b..6e5fbb4 100644
--- a/chrono/agendas/migrations/0016_desk.py
+++ b/chrono/agendas/migrations/0016_desk.py
@@ -14,13 +14,14 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Desk',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
                 ('label', models.CharField(max_length=150, verbose_name='Label')),
                 ('slug', models.SlugField(max_length=150, verbose_name='Identifier')),
                 ('agenda', models.ForeignKey(to='agendas.Agenda', on_delete=models.CASCADE)),
             ],
-            options={
-                'ordering': ['label'],
-            },
+            options={'ordering': ['label'],},
         ),
     ]
diff --git a/chrono/agendas/migrations/0017_timeperiod_desk.py b/chrono/agendas/migrations/0017_timeperiod_desk.py
index ecb47a0..77caf7a 100644
--- a/chrono/agendas/migrations/0017_timeperiod_desk.py
+++ b/chrono/agendas/migrations/0017_timeperiod_desk.py
@@ -9,7 +9,8 @@ def set_timeperiod_desk(apps, schema_editor):
     Desk = apps.get_model('agendas', 'Desk')
     for time_period in TimePeriod.objects.all():
         desk, created = Desk.objects.get_or_create(
-            label='Guichet 1', slug='guichet-1', agenda=time_period.agenda)
+            label='Guichet 1', slug='guichet-1', agenda=time_period.agenda
+        )
         time_period.desk = desk
         time_period.save()
 
@@ -36,8 +37,5 @@ class Migration(migrations.Migration):
             name='desk',
             field=models.ForeignKey(to='agendas.Desk', on_delete=models.CASCADE),
         ),
-        migrations.RemoveField(
-            model_name='timeperiod',
-            name='agenda',
-        ),
+        migrations.RemoveField(model_name='timeperiod', name='agenda',),
     ]
diff --git a/chrono/agendas/migrations/0018_event_desk.py b/chrono/agendas/migrations/0018_event_desk.py
index db08d39..86a9d77 100644
--- a/chrono/agendas/migrations/0018_event_desk.py
+++ b/chrono/agendas/migrations/0018_event_desk.py
@@ -11,8 +11,7 @@ def set_event_desk(apps, schema_editor):
         if not event.agenda.kind == 'meetings':
             continue
 
-        desk, created = Desk.objects.get_or_create(
-            label='Guichet 1', slug='guichet-1', agenda=event.agenda)
+        desk, created = Desk.objects.get_or_create(label='Guichet 1', slug='guichet-1', agenda=event.agenda)
         event.desk = desk
         event.save()
 
@@ -33,5 +32,5 @@ class Migration(migrations.Migration):
             name='desk',
             field=models.ForeignKey(to='agendas.Desk', null=True, on_delete=models.CASCADE),
         ),
-        migrations.RunPython(set_event_desk, unset_event_desk)
+        migrations.RunPython(set_event_desk, unset_event_desk),
     ]
diff --git a/chrono/agendas/migrations/0019_timeperiodexception.py b/chrono/agendas/migrations/0019_timeperiodexception.py
index 55e8d47..578d8f1 100644
--- a/chrono/agendas/migrations/0019_timeperiodexception.py
+++ b/chrono/agendas/migrations/0019_timeperiodexception.py
@@ -14,14 +14,18 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='TimePeriodException',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('label', models.CharField(max_length=150, null=True, verbose_name='Optional Label', blank=True)),
+                (
+                    'id',
+                    models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+                ),
+                (
+                    'label',
+                    models.CharField(max_length=150, null=True, verbose_name='Optional Label', blank=True),
+                ),
                 ('start_datetime', models.DateTimeField(verbose_name='Exception start time')),
                 ('end_datetime', models.DateTimeField(verbose_name='Exception end time')),
                 ('desk', models.ForeignKey(to='agendas.Desk', on_delete=models.CASCADE)),
             ],
-            options={
-                'ordering': ['start_datetime'],
-            },
+            options={'ordering': ['start_datetime'],},
         ),
     ]
diff --git a/chrono/agendas/migrations/0020_auto_20171102_1021.py b/chrono/agendas/migrations/0020_auto_20171102_1021.py
index 40bb940..4bdb3d4 100644
--- a/chrono/agendas/migrations/0020_auto_20171102_1021.py
+++ b/chrono/agendas/migrations/0020_auto_20171102_1021.py
@@ -1,8 +1,9 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import migrations, models
 import datetime
+
+from django.db import migrations, models
 from django.utils.timezone import utc
 
 
@@ -26,7 +27,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='timeperiodexception',
             name='update_datetime',
-            field=models.DateTimeField(default=datetime.datetime(2017, 11, 2, 10, 21, 1, 826837, tzinfo=utc), auto_now=True),
+            field=models.DateTimeField(
+                default=datetime.datetime(2017, 11, 2, 10, 21, 1, 826837, tzinfo=utc), auto_now=True
+            ),
             preserve_default=False,
         ),
     ]
diff --git a/chrono/agendas/migrations/0021_auto_20171126_1330.py b/chrono/agendas/migrations/0021_auto_20171126_1330.py
index 47b5576..439204e 100644
--- a/chrono/agendas/migrations/0021_auto_20171126_1330.py
+++ b/chrono/agendas/migrations/0021_auto_20171126_1330.py
@@ -11,19 +11,11 @@ class Migration(migrations.Migration):
     ]
 
     operations = [
+        migrations.AddField(model_name='booking', name='backoffice_url', field=models.URLField(blank=True),),
         migrations.AddField(
-            model_name='booking',
-            name='backoffice_url',
-            field=models.URLField(blank=True),
+            model_name='booking', name='label', field=models.CharField(max_length=250, blank=True),
         ),
         migrations.AddField(
-            model_name='booking',
-            name='label',
-            field=models.CharField(max_length=250, blank=True),
-        ),
-        migrations.AddField(
-            model_name='booking',
-            name='user_name',
-            field=models.CharField(max_length=250, blank=True),
+            model_name='booking', name='user_name', field=models.CharField(max_length=250, blank=True),
         ),
     ]
diff --git a/chrono/agendas/migrations/0022_auto_20171202_1828.py b/chrono/agendas/migrations/0022_auto_20171202_1828.py
index d987880..0773d48 100644
--- a/chrono/agendas/migrations/0022_auto_20171202_1828.py
+++ b/chrono/agendas/migrations/0022_auto_20171202_1828.py
@@ -17,9 +17,7 @@ class Migration(migrations.Migration):
             field=models.SlugField(max_length=160, verbose_name='Identifier'),
         ),
         migrations.AlterField(
-            model_name='desk',
-            name='slug',
-            field=models.SlugField(max_length=160, verbose_name='Identifier'),
+            model_name='desk', name='slug', field=models.SlugField(max_length=160, verbose_name='Identifier'),
         ),
         migrations.AlterField(
             model_name='meetingtype',
diff --git a/chrono/agendas/migrations/0023_auto_20171202_1835.py b/chrono/agendas/migrations/0023_auto_20171202_1835.py
index f8d7a02..b567be4 100644
--- a/chrono/agendas/migrations/0023_auto_20171202_1835.py
+++ b/chrono/agendas/migrations/0023_auto_20171202_1835.py
@@ -14,6 +14,8 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='desk',
             name='timeperiod_exceptions_remote_url',
-            field=models.URLField(max_length=500, verbose_name='URL to fetch time period exceptions from', blank=True),
+            field=models.URLField(
+                max_length=500, verbose_name='URL to fetch time period exceptions from', blank=True
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0024_auto_20180426_1127.py b/chrono/agendas/migrations/0024_auto_20180426_1127.py
index 2ac2a19..5638943 100644
--- a/chrono/agendas/migrations/0024_auto_20180426_1127.py
+++ b/chrono/agendas/migrations/0024_auto_20180426_1127.py
@@ -12,10 +12,7 @@ class Migration(migrations.Migration):
     ]
 
     operations = [
-        migrations.AlterModelOptions(
-            name='meetingtype',
-            options={'ordering': ['duration', 'label']},
-        ),
+        migrations.AlterModelOptions(name='meetingtype', options={'ordering': ['duration', 'label']},),
         migrations.AddField(
             model_name='timeperiodexception',
             name='recurrence_id',
diff --git a/chrono/agendas/migrations/0025_auto_20181206_1252.py b/chrono/agendas/migrations/0025_auto_20181206_1252.py
index 637f697..be9d1d6 100644
--- a/chrono/agendas/migrations/0025_auto_20181206_1252.py
+++ b/chrono/agendas/migrations/0025_auto_20181206_1252.py
@@ -2,8 +2,8 @@
 # Generated by Django 1.11.12 on 2018-12-06 12:52
 from __future__ import unicode_literals
 
-from django.db import migrations, models
 import django.db.models.deletion
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -16,11 +16,27 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='agenda',
             name='edit_role',
-            field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='auth.Group', verbose_name='Edit Role'),
+            field=models.ForeignKey(
+                blank=True,
+                default=None,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name='+',
+                to='auth.Group',
+                verbose_name='Edit Role',
+            ),
         ),
         migrations.AlterField(
             model_name='agenda',
             name='view_role',
-            field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='auth.Group', verbose_name='View Role'),
+            field=models.ForeignKey(
+                blank=True,
+                default=None,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                related_name='+',
+                to='auth.Group',
+                verbose_name='View Role',
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0027_event_description.py b/chrono/agendas/migrations/0027_event_description.py
index 6a1169f..8c44789 100644
--- a/chrono/agendas/migrations/0027_event_description.py
+++ b/chrono/agendas/migrations/0027_event_description.py
@@ -15,6 +15,8 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='event',
             name='description',
-            field=models.TextField(blank=True, help_text='Optional event description.', null=True, verbose_name='Description'),
+            field=models.TextField(
+                blank=True, help_text='Optional event description.', null=True, verbose_name='Description'
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0028_event_slug.py b/chrono/agendas/migrations/0028_event_slug.py
index 912b229..d9bc4c2 100644
--- a/chrono/agendas/migrations/0028_event_slug.py
+++ b/chrono/agendas/migrations/0028_event_slug.py
@@ -15,7 +15,9 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='event',
             name='slug',
-            field=models.SlugField(default=None, null=True, blank=True, max_length=160, verbose_name='Identifier'),
+            field=models.SlugField(
+                default=None, null=True, blank=True, max_length=160, verbose_name='Identifier'
+            ),
             preserve_default=False,
         ),
     ]
diff --git a/chrono/agendas/migrations/0029_auto_20191106_1320.py b/chrono/agendas/migrations/0029_auto_20191106_1320.py
index 78a6971..010c159 100644
--- a/chrono/agendas/migrations/0029_auto_20191106_1320.py
+++ b/chrono/agendas/migrations/0029_auto_20191106_1320.py
@@ -15,6 +15,8 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='event',
             name='slug',
-            field=models.SlugField(default=None, null=True, blank=True, max_length=160, verbose_name='Identifier'),
+            field=models.SlugField(
+                default=None, null=True, blank=True, max_length=160, verbose_name='Identifier'
+            ),
         ),
     ]
diff --git a/chrono/agendas/migrations/0030_auto_20191107_1200.py b/chrono/agendas/migrations/0030_auto_20191107_1200.py
index 8e551bd..3348250 100644
--- a/chrono/agendas/migrations/0030_auto_20191107_1200.py
+++ b/chrono/agendas/migrations/0030_auto_20191107_1200.py
@@ -39,7 +39,11 @@ def set_slug_on_desks(apps, schema_editor):
 def set_slug_on_meetingtypes(apps, schema_editor):
     MeetingType = apps.get_model('agendas', 'MeetingType')
     for meetingtype in MeetingType.objects.all().order_by('-pk'):
-        if not MeetingType.objects.filter(slug=meetingtype.slug, agenda=meetingtype.agenda).exclude(pk=meetingtype.pk).exists():
+        if (
+            not MeetingType.objects.filter(slug=meetingtype.slug, agenda=meetingtype.agenda)
+            .exclude(pk=meetingtype.pk)
+            .exists()
+        ):
             continue
         meetingtype.slug = generate_slug(meetingtype, agenda=meetingtype.agenda)
         meetingtype.save(update_fields=['slug'])
diff --git a/chrono/agendas/migrations/0031_auto_20191107_1225.py b/chrono/agendas/migrations/0031_auto_20191107_1225.py
index e0c900c..e957216 100644
--- a/chrono/agendas/migrations/0031_auto_20191107_1225.py
+++ b/chrono/agendas/migrations/0031_auto_20191107_1225.py
@@ -17,12 +17,6 @@ class Migration(migrations.Migration):
             name='slug',
             field=models.SlugField(max_length=160, unique=True, verbose_name='Identifier'),
         ),
-        migrations.AlterUniqueTogether(
-            name='desk',
-            unique_together=set([('agenda', 'slug')]),
-        ),
-        migrations.AlterUniqueTogether(
-            name='meetingtype',
-            unique_together=set([('agenda', 'slug')]),
-        ),
+        migrations.AlterUniqueTogether(name='desk', unique_together=set([('agenda', 'slug')]),),
+        migrations.AlterUniqueTogether(name='meetingtype', unique_together=set([('agenda', 'slug')]),),
     ]
diff --git a/chrono/agendas/migrations/0032_auto_20191127_0919.py b/chrono/agendas/migrations/0032_auto_20191127_0919.py
index ab55503..0e0e112 100644
--- a/chrono/agendas/migrations/0032_auto_20191127_0919.py
+++ b/chrono/agendas/migrations/0032_auto_20191127_0919.py
@@ -15,10 +15,9 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='event',
             name='slug',
-            field=models.SlugField(default=None, null=True, blank=True, max_length=160, verbose_name='Identifier')
-        ),
-        migrations.AlterUniqueTogether(
-            name='event',
-            unique_together=set([('agenda', 'slug')]),
+            field=models.SlugField(
+                default=None, null=True, blank=True, max_length=160, verbose_name='Identifier'
+            ),
         ),
+        migrations.AlterUniqueTogether(name='event', unique_together=set([('agenda', 'slug')]),),
     ]
diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py
index c5c8ae1..ab90a80 100644
--- a/chrono/agendas/models.py
+++ b/chrono/agendas/models.py
@@ -17,9 +17,9 @@
 
 import datetime
 import math
+
 import requests
 import vobject
-
 from django.conf import settings
 from django.contrib.auth.models import Group
 from django.core.exceptions import ValidationError
@@ -30,14 +30,12 @@ from django.utils.dates import WEEKDAYS
 from django.utils.encoding import force_text, python_2_unicode_compatible
 from django.utils.formats import date_format
 from django.utils.text import slugify
-from django.utils.timezone import localtime, now, make_aware, make_naive, is_aware
+from django.utils.timezone import is_aware, localtime, make_aware, make_naive, now
 from django.utils.translation import ugettext_lazy as _
-
 from jsonfield import JSONField
 
 from ..interval import Intervals
 
-
 AGENDA_KINDS = (
     ('events', _('Events')),
     ('meetings', _('Meetings')),
@@ -71,16 +69,28 @@ class Agenda(models.Model):
     label = models.CharField(_('Label'), max_length=150)
     slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
     kind = models.CharField(_('Kind'), max_length=20, choices=AGENDA_KINDS, default='events')
-    minimal_booking_delay = models.PositiveIntegerField(
-            _('Minimal booking delay (in days)'), default=1)
+    minimal_booking_delay = models.PositiveIntegerField(_('Minimal booking delay (in days)'), default=1)
     maximal_booking_delay = models.PositiveIntegerField(
-            _('Maximal booking delay (in days)'), default=56) # eight weeks
-    edit_role = models.ForeignKey(Group, blank=True, null=True, default=None,
-            related_name='+', verbose_name=_('Edit Role'),
-            on_delete=models.SET_NULL)
-    view_role = models.ForeignKey(Group, blank=True, null=True, default=None,
-            related_name='+', verbose_name=_('View Role'),
-            on_delete=models.SET_NULL)
+        _('Maximal booking delay (in days)'), default=56
+    )  # eight weeks
+    edit_role = models.ForeignKey(
+        Group,
+        blank=True,
+        null=True,
+        default=None,
+        related_name='+',
+        verbose_name=_('Edit Role'),
+        on_delete=models.SET_NULL,
+    )
+    view_role = models.ForeignKey(
+        Group,
+        blank=True,
+        null=True,
+        default=None,
+        related_name='+',
+        verbose_name=_('View Role'),
+        on_delete=models.SET_NULL,
+    )
 
     class Meta:
         ordering = ['label']
@@ -124,7 +134,7 @@ class Agenda(models.Model):
             'permissions': {
                 'view': self.view_role.name if self.view_role else None,
                 'edit': self.edit_role.name if self.edit_role else None,
-            }
+            },
         }
         if self.kind == 'events':
             agenda['events'] = [x.export_json() for x in self.event_set.all()]
@@ -170,6 +180,7 @@ class Agenda(models.Model):
                 Desk.import_json(desk).save()
         return created
 
+
 WEEKDAYS_LIST = sorted(WEEKDAYS.items(), key=lambda x: x[0])
 
 
@@ -198,9 +209,10 @@ class TimePeriod(models.Model):
 
     def __str__(self):
         return u'%s / %s → %s' % (
-                force_text(WEEKDAYS[self.weekday]),
-                date_format(self.start_time, 'TIME_FORMAT'),
-                date_format(self.end_time, 'TIME_FORMAT'))
+            force_text(WEEKDAYS[self.weekday]),
+            date_format(self.start_time, 'TIME_FORMAT'),
+            date_format(self.end_time, 'TIME_FORMAT'),
+        )
 
     @property
     def weekday_str(self):
@@ -212,9 +224,9 @@ class TimePeriod(models.Model):
 
     def export_json(self):
         return {
-           'weekday': self.weekday,
-           'start_time': self.start_time.strftime('%H:%M'),
-           'end_time': self.end_time.strftime('%H:%M'),
+            'weekday': self.weekday,
+            'start_time': self.start_time.strftime('%H:%M'),
+            'end_time': self.end_time.strftime('%H:%M'),
         }
 
     def get_time_slots(self, min_datetime, max_datetime, meeting_type):
@@ -223,19 +235,21 @@ class TimePeriod(models.Model):
         min_datetime = make_naive(min_datetime)
         max_datetime = make_naive(max_datetime)
 
-        real_min_datetime = min_datetime + datetime.timedelta(
-                days=self.weekday - min_datetime.weekday())
+        real_min_datetime = min_datetime + datetime.timedelta(days=self.weekday - min_datetime.weekday())
         if real_min_datetime < min_datetime:
             real_min_datetime += datetime.timedelta(days=7)
 
-        event_datetime = real_min_datetime.replace(hour=self.start_time.hour,
-                minute=self.start_time.minute, second=0, microsecond=0)
+        event_datetime = real_min_datetime.replace(
+            hour=self.start_time.hour, minute=self.start_time.minute, second=0, microsecond=0
+        )
         while event_datetime < max_datetime:
             end_time = event_datetime + meeting_duration
             next_time = event_datetime + duration
             if end_time.time() > self.end_time or event_datetime.date() != next_time.date():
                 # back to morning
-                event_datetime = event_datetime.replace(hour=self.start_time.hour, minute=self.start_time.minute)
+                event_datetime = event_datetime.replace(
+                    hour=self.start_time.hour, minute=self.start_time.minute
+                )
                 # but next week
                 event_datetime += datetime.timedelta(days=7)
                 next_time = event_datetime + duration
@@ -243,7 +257,9 @@ class TimePeriod(models.Model):
             if event_datetime > max_datetime:
                 break
 
-            yield TimeSlot(start_datetime=make_aware(event_datetime), meeting_type=meeting_type, desk=self.desk)
+            yield TimeSlot(
+                start_datetime=make_aware(event_datetime), meeting_type=meeting_type, desk=self.desk
+            )
             event_datetime = next_time
 
 
@@ -265,7 +281,8 @@ class MeetingType(models.Model):
     @classmethod
     def import_json(cls, data):
         meeting_type, created = cls.objects.get_or_create(
-            slug=data['slug'], agenda=data['agenda'], defaults=data)
+            slug=data['slug'], agenda=data['agenda'], defaults=data
+        )
         if not created:
             for k, v in data.items():
                 setattr(meeting_type, k, v)
@@ -273,9 +290,9 @@ class MeetingType(models.Model):
 
     def export_json(self):
         return {
-           'label': self.label,
-           'slug': self.slug,
-           'duration': self.duration,
+            'label': self.label,
+            'slug': self.slug,
+            'duration': self.duration,
         }
 
 
@@ -284,13 +301,18 @@ class Event(models.Model):
     agenda = models.ForeignKey(Agenda, on_delete=models.CASCADE)
     start_datetime = models.DateTimeField(_('Date/time'))
     places = models.PositiveIntegerField(_('Places'))
-    waiting_list_places = models.PositiveIntegerField(
-            _('Places in waiting list'), default=0)
-    label = models.CharField(_('Label'), max_length=150, null=True, blank=True,
-            help_text=_('Optional label to identify this date.'))
+    waiting_list_places = models.PositiveIntegerField(_('Places in waiting list'), default=0)
+    label = models.CharField(
+        _('Label'),
+        max_length=150,
+        null=True,
+        blank=True,
+        help_text=_('Optional label to identify this date.'),
+    )
     slug = models.SlugField(_('Identifier'), max_length=160, null=True, blank=True, default=None)
-    description = models.TextField(_('Description'), null=True, blank=True,
-            help_text=_('Optional event description.'))
+    description = models.TextField(
+        _('Description'), null=True, blank=True, help_text=_('Optional event description.')
+    )
     full = models.BooleanField(default=False)
     meeting_type = models.ForeignKey(MeetingType, null=True, on_delete=models.CASCADE)
     desk = models.ForeignKey('Desk', null=True, on_delete=models.CASCADE)
@@ -310,14 +332,24 @@ class Event(models.Model):
 
     def check_full(self):
         self.full = bool(
-            (self.booked_places >= self.places and self.waiting_list_places == 0) or
-            (self.waiting_list_places and self.waiting_list >= self.waiting_list_places))
+            (self.booked_places >= self.places and self.waiting_list_places == 0)
+            or (self.waiting_list_places and self.waiting_list >= self.waiting_list_places)
+        )
 
     def in_bookable_period(self):
-        if localtime(now()).date() > localtime(self.start_datetime - datetime.timedelta(days=self.agenda.minimal_booking_delay)).date():
+        if (
+            localtime(now()).date()
+            > localtime(
+                self.start_datetime - datetime.timedelta(days=self.agenda.minimal_booking_delay)
+            ).date()
+        ):
             return False
         if self.agenda.maximal_booking_delay and (
-                localtime(now()).date() <= localtime(self.start_datetime - datetime.timedelta(days=self.agenda.maximal_booking_delay)).date()):
+            localtime(now()).date()
+            <= localtime(
+                self.start_datetime - datetime.timedelta(days=self.agenda.maximal_booking_delay)
+            ).date()
+        ):
             return False
         if self.start_datetime < now():
             # past the event date, we may want in the future to allow for some
@@ -327,13 +359,11 @@ class Event(models.Model):
 
     @property
     def booked_places(self):
-        return self.booking_set.filter(cancellation_datetime__isnull=True,
-                in_waiting_list=False).count()
+        return self.booking_set.filter(cancellation_datetime__isnull=True, in_waiting_list=False).count()
 
     @property
     def waiting_list(self):
-        return self.booking_set.filter(cancellation_datetime__isnull=True,
-                in_waiting_list=True).count()
+        return self.booking_set.filter(cancellation_datetime__isnull=True, in_waiting_list=True).count()
 
     @property
     def end_datetime(self):
@@ -344,8 +374,9 @@ class Event(models.Model):
 
     @classmethod
     def import_json(cls, data):
-        data['start_datetime'] = make_aware(datetime.datetime.strptime(
-            data['start_datetime'], '%Y-%m-%d %H:%M:%S'))
+        data['start_datetime'] = make_aware(
+            datetime.datetime.strptime(data['start_datetime'], '%Y-%m-%d %H:%M:%S')
+        )
         if data.get('slug'):
             event, created = cls.objects.get_or_create(slug=data['slug'], defaults=data)
             if not created:
@@ -372,11 +403,14 @@ class Booking(models.Model):
     in_waiting_list = models.BooleanField(default=False)
     creation_datetime = models.DateTimeField(auto_now_add=True)
     # primary booking is used to group multiple bookings together
-    primary_booking = models.ForeignKey('self', null=True,
-            on_delete=models.CASCADE, related_name='secondary_booking_set')
+    primary_booking = models.ForeignKey(
+        'self', null=True, on_delete=models.CASCADE, related_name='secondary_booking_set'
+    )
 
     label = models.CharField(max_length=250, blank=True)
-    user_display_label = models.CharField(verbose_name=_('Label displayed to user'), max_length=250, blank=True)
+    user_display_label = models.CharField(
+        verbose_name=_('Label displayed to user'), max_length=250, blank=True
+    )
     user_name = models.CharField(max_length=250, blank=True)
     backoffice_url = models.URLField(blank=True)
 
@@ -405,14 +439,20 @@ class Booking(models.Model):
         ics = vobject.iCalendar()
         ics.add('prodid').value = '-//Entr\'ouvert//NON SGML Publik'
         vevent = vobject.newFromBehavior('vevent')
-        vevent.add('uid').value = '%s-%s-%s' % (self.event.start_datetime.isoformat(), self.event.agenda.pk, self.pk)
+        vevent.add('uid').value = '%s-%s-%s' % (
+            self.event.start_datetime.isoformat(),
+            self.event.agenda.pk,
+            self.pk,
+        )
 
         vevent.add('summary').value = self.user_display_label or self.label
         vevent.add('dtstart').value = self.event.start_datetime
         if self.user_name:
             vevent.add('attendee').value = self.user_name
         if self.event.meeting_type:
-            vevent.add('dtend').value = self.event.start_datetime + datetime.timedelta(minutes=self.event.meeting_type.duration)
+            vevent.add('dtend').value = self.event.start_datetime + datetime.timedelta(
+                minutes=self.event.meeting_type.duration
+            )
 
         for field in ('description', 'location', 'comment', 'url'):
             field_value = request and request.GET.get(field) or self.extra_data.get(field)
@@ -422,15 +462,14 @@ class Booking(models.Model):
         return ics.serialize()
 
 
-
 @python_2_unicode_compatible
 class Desk(models.Model):
     agenda = models.ForeignKey(Agenda, on_delete=models.CASCADE)
     label = models.CharField(_('Label'), max_length=150)
     slug = models.SlugField(_('Identifier'), max_length=160)
     timeperiod_exceptions_remote_url = models.URLField(
-            _('URL to fetch time period exceptions from'),
-            blank=True, max_length=500)
+        _('URL to fetch time period exceptions from'), blank=True, max_length=500
+    )
 
     def __str__(self):
         return self.label
@@ -448,8 +487,7 @@ class Desk(models.Model):
     def import_json(cls, data):
         timeperiods = data.pop('timeperiods')
         exceptions = data.pop('exceptions')
-        instance, created = cls.objects.get_or_create(
-            slug=data['slug'], agenda=data['agenda'], defaults=data)
+        instance, created = cls.objects.get_or_create(slug=data['slug'], agenda=data['agenda'], defaults=data)
         if not created:
             for k, v in data.items():
                 setattr(instance, k, v)
@@ -462,21 +500,24 @@ class Desk(models.Model):
         return instance
 
     def export_json(self):
-        return {'label': self.label,
-                'slug': self.slug,
-                'timeperiods': [time_period.export_json() for time_period in self.timeperiod_set.all()],
-                'exceptions': [exception.export_json() for exception in self.timeperiodexception_set.all()]
-                }
+        return {
+            'label': self.label,
+            'slug': self.slug,
+            'timeperiods': [time_period.export_json() for time_period in self.timeperiod_set.all()],
+            'exceptions': [exception.export_json() for exception in self.timeperiodexception_set.all()],
+        }
 
     def get_exceptions_within_two_weeks(self):
         in_two_weeks = make_aware(datetime.datetime.today() + datetime.timedelta(days=14))
         exceptions = self.timeperiodexception_set.filter(end_datetime__gte=now()).filter(
-                Q(end_datetime__lte=in_two_weeks) | Q(start_datetime__lt=now()))
+            Q(end_datetime__lte=in_two_weeks) | Q(start_datetime__lt=now())
+        )
         if exceptions.exists():
             return exceptions
         # if none found within the 2 coming weeks, return the next one
-        next_exception = self.timeperiodexception_set.filter(
-            start_datetime__gte=now()).order_by('start_datetime').first()
+        next_exception = (
+            self.timeperiodexception_set.filter(start_datetime__gte=now()).order_by('start_datetime').first()
+        )
         if next_exception:
             return [next_exception]
         return []
@@ -491,12 +532,14 @@ class Desk(models.Model):
             response.raise_for_status()
         except requests.HTTPError as e:
             raise ICSError(
-                _('Failed to retrieve remote calendar (%(url)s, HTTP error %(status_code)s).') %
-                {'url': url, 'status_code': e.response.status_code})
+                _('Failed to retrieve remote calendar (%(url)s, HTTP error %(status_code)s).')
+                % {'url': url, 'status_code': e.response.status_code}
+            )
         except requests.RequestException as e:
             raise ICSError(
-                _('Failed to retrieve remote calendar (%(url)s, %(exception)s).') %
-                {'url': url, 'exception': e})
+                _('Failed to retrieve remote calendar (%(url)s, %(exception)s).')
+                % {'url': url, 'exception': e}
+            )
 
         return self.create_timeperiod_exceptions_from_ics(response.text, keep_synced_by_uid=True)
 
@@ -582,7 +625,9 @@ class Desk(models.Model):
                         if end_dt < update_datetime:
                             TimePeriodException.objects.filter(**kwargs).update(**event)
                         else:
-                            obj, created = TimePeriodException.objects.update_or_create(defaults=event, **kwargs)
+                            obj, created = TimePeriodException.objects.update_or_create(
+                                defaults=event, **kwargs
+                            )
                             if created:
                                 total_created += 1
                     # delete unseen occurrences
@@ -591,8 +636,9 @@ class Desk(models.Model):
 
             if keep_synced_by_uid:
                 # delete all outdated exceptions from remote calendar
-                TimePeriodException.objects.filter(update_datetime__lt=update_datetime,
-                                    desk=self).exclude(external_id='').delete()
+                TimePeriodException.objects.filter(update_datetime__lt=update_datetime, desk=self).exclude(
+                    external_id=''
+                ).delete()
 
         return total_created
 
@@ -606,8 +652,8 @@ class Desk(models.Model):
         aware_date = make_aware(datetime.datetime(date.year, date.month, date.day))
         aware_next_date = aware_date + datetime.timedelta(days=1)
         for exception in self.timeperiodexception_set.filter(
-                start_datetime__lt=aware_next_date,
-                end_datetime__gt=aware_date):
+            start_datetime__lt=aware_next_date, end_datetime__gt=aware_date
+        ):
             openslots.remove(exception.start_datetime, exception.end_datetime)
 
         return openslots.search(aware_date, aware_next_date)
@@ -634,18 +680,21 @@ class TimePeriodException(models.Model):
                 exc_repr = u'%s' % date_format(localtime(self.start_datetime), 'SHORT_DATE_FORMAT')
             else:
                 exc_repr = u'%s → %s' % (
-                        date_format(localtime(self.start_datetime), 'SHORT_DATE_FORMAT'),
-                        date_format(localtime(self.end_datetime), 'SHORT_DATE_FORMAT'))
+                    date_format(localtime(self.start_datetime), 'SHORT_DATE_FORMAT'),
+                    date_format(localtime(self.end_datetime), 'SHORT_DATE_FORMAT'),
+                )
         else:
             if localtime(self.start_datetime).date() == localtime(self.end_datetime).date():
                 # same day
                 exc_repr = u'%s → %s' % (
-                        date_format(localtime(self.start_datetime), 'SHORT_DATETIME_FORMAT'),
-                        date_format(localtime(self.end_datetime), 'TIME_FORMAT'))
+                    date_format(localtime(self.start_datetime), 'SHORT_DATETIME_FORMAT'),
+                    date_format(localtime(self.end_datetime), 'TIME_FORMAT'),
+                )
             else:
                 exc_repr = u'%s → %s' % (
-                        date_format(localtime(self.start_datetime), 'SHORT_DATETIME_FORMAT'),
-                        date_format(localtime(self.end_datetime), 'SHORT_DATETIME_FORMAT'))
+                    date_format(localtime(self.start_datetime), 'SHORT_DATETIME_FORMAT'),
+                    date_format(localtime(self.end_datetime), 'SHORT_DATETIME_FORMAT'),
+                )
 
         if self.label:
             exc_repr = u'%s (%s)' % (self.label, exc_repr)
@@ -662,9 +711,8 @@ class TimePeriodException(models.Model):
             # incomplete time period, can't tell
             return False
         for event in Event.objects.filter(
-                desk=self.desk,
-                booking__isnull=False,
-                booking__cancellation_datetime__isnull=True):
+            desk=self.desk, booking__isnull=False, booking__cancellation_datetime__isnull=True
+        ):
             if self.start_datetime <= event.start_datetime < self.end_datetime:
                 return True
         return False
diff --git a/chrono/api/urls.py b/chrono/api/urls.py
index 79ee179..d9c5121 100644
--- a/chrono/api/urls.py
+++ b/chrono/api/urls.py
@@ -21,29 +21,32 @@ from . import views
 urlpatterns = [
     url(r'agenda/$', views.agendas),
     url(r'agenda/(?P<agenda_identifier>[\w-]+)/$', views.agenda_detail),
-
     url(r'agenda/(?P<agenda_identifier>[\w-]+)/datetimes/$', views.datetimes, name='api-agenda-datetimes'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslot/(?P<event_identifier>[\w:-]+)/$',
-        views.fillslot, name='api-fillslot'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslots/$',
-        views.fillslots, name='api-agenda-fillslots'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_identifier>[\w-]+)/$', views.slot_status,
-        name='api-event-status'),
-
-    url(r'agenda/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',
-        views.meeting_datetimes, name='api-agenda-meeting-datetimes-legacy'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/meetings/$',
-        views.meeting_list, name='api-agenda-meetings'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/desks/$',
-        views.agenda_desk_list, name='api-agenda-desks'),
-    url(r'agenda/(?P<agenda_identifier>[\w-]+)/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',
-        views.meeting_datetimes, name='api-agenda-meeting-datetimes'),
-
+    url(
+        r'agenda/(?P<agenda_identifier>[\w-]+)/fillslot/(?P<event_identifier>[\w:-]+)/$',
+        views.fillslot,
+        name='api-fillslot',
+    ),
+    url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslots/$', views.fillslots, name='api-agenda-fillslots'),
+    url(
+        r'agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_identifier>[\w-]+)/$',
+        views.slot_status,
+        name='api-event-status',
+    ),
+    url(
+        r'agenda/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',
+        views.meeting_datetimes,
+        name='api-agenda-meeting-datetimes-legacy',
+    ),
+    url(r'agenda/(?P<agenda_identifier>[\w-]+)/meetings/$', views.meeting_list, name='api-agenda-meetings'),
+    url(r'agenda/(?P<agenda_identifier>[\w-]+)/desks/$', views.agenda_desk_list, name='api-agenda-desks'),
+    url(
+        r'agenda/(?P<agenda_identifier>[\w-]+)/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',
+        views.meeting_datetimes,
+        name='api-agenda-meeting-datetimes',
+    ),
     url(r'booking/(?P<booking_pk>\w+)/$', views.booking),
-    url(r'booking/(?P<booking_pk>\w+)/cancel/$', views.cancel_booking,
-        name='api-cancel-booking'),
-    url(r'booking/(?P<booking_pk>\w+)/accept/$', views.accept_booking,
-        name='api-accept-booking'),
-    url(r'booking/(?P<booking_pk>\w+)/ics/$', views.booking_ics,
-        name='api-booking-ics'),
+    url(r'booking/(?P<booking_pk>\w+)/cancel/$', views.cancel_booking, name='api-cancel-booking'),
+    url(r'booking/(?P<booking_pk>\w+)/accept/$', views.accept_booking, name='api-accept-booking'),
+    url(r'booking/(?P<booking_pk>\w+)/ics/$', views.booking_ics, name='api-booking-ics'),
 ]
diff --git a/chrono/api/views.py b/chrono/api/views.py
index d34f729..0444893 100644
--- a/chrono/api/views.py
+++ b/chrono/api/views.py
@@ -14,8 +14,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from collections import defaultdict
 import datetime
+from collections import defaultdict
 
 from django.db import transaction
 from django.http import Http404, HttpResponse
@@ -23,17 +23,15 @@ from django.shortcuts import get_object_or_404
 from django.urls import reverse
 from django.utils.dateparse import parse_date
 from django.utils.encoding import force_text
-from django.utils.timezone import now, make_aware, localtime
+from django.utils.timezone import localtime, make_aware, now
 from django.utils.translation import gettext_noop
 from django.utils.translation import ugettext_lazy as _
-
 from rest_framework import permissions, serializers, status
-
 from rest_framework.views import APIView
 
 from chrono.api.utils import Response
-from ..agendas.models import (Agenda, Event, Booking, MeetingType,
-                              TimePeriod, Desk)
+
+from ..agendas.models import Agenda, Booking, Desk, Event, MeetingType, TimePeriod
 from ..interval import Intervals
 
 
@@ -44,7 +42,9 @@ def format_response_datetime(dt):
 def get_exceptions_by_desk(agenda):
     exceptions_by_desk = {}
     for desk in Desk.objects.filter(agenda=agenda).prefetch_related('timeperiodexception_set'):
-        exceptions_by_desk[desk.id] = [(exc.start_datetime, exc.end_datetime) for exc in desk.timeperiodexception_set.all()]
+        exceptions_by_desk[desk.id] = [
+            (exc.start_datetime, exc.end_datetime) for exc in desk.timeperiodexception_set.all()
+        ]
     return exceptions_by_desk
 
 
@@ -58,14 +58,16 @@ def get_all_slots(agenda, meeting_type):
     time_period_filters = {
         'min_datetime': min_datetime,
         'max_datetime': max_datetime,
-        'meeting_type': meeting_type
+        'meeting_type': meeting_type,
     }
 
     base_date = now().date()
     open_slots_by_desk = defaultdict(lambda: Intervals())
     for time_period in TimePeriod.objects.filter(desk__agenda=agenda):
-        duration = (datetime.datetime.combine(base_date, time_period.end_time) -
-                    datetime.datetime.combine(base_date, time_period.start_time)).seconds / 60
+        duration = (
+            datetime.datetime.combine(base_date, time_period.end_time)
+            - datetime.datetime.combine(base_date, time_period.start_time)
+        ).seconds / 60
         if duration < meeting_type.duration:
             # skip time period that can't even hold a single meeting
             continue
@@ -80,11 +82,15 @@ def get_all_slots(agenda, meeting_type):
             begin, end = interval
             open_slots_by_desk[desk].remove_overlap(localtime(begin), localtime(end))
 
-    for event in agenda.event_set.filter(
-            agenda=agenda, start_datetime__gte=min_datetime,
-            start_datetime__lte=max_datetime + datetime.timedelta(meeting_type.duration)).select_related(
-                'meeting_type').exclude(
-                        booking__cancellation_datetime__isnull=False):
+    for event in (
+        agenda.event_set.filter(
+            agenda=agenda,
+            start_datetime__gte=min_datetime,
+            start_datetime__lte=max_datetime + datetime.timedelta(meeting_type.duration),
+        )
+        .select_related('meeting_type')
+        .exclude(booking__cancellation_datetime__isnull=False)
+    ):
         for slot in open_slots_by_desk[event.desk_id].search_data(event.start_datetime, event.end_datetime):
             slot.full = True
 
@@ -98,7 +104,7 @@ def get_all_slots(agenda, meeting_type):
 def get_agenda_detail(request, agenda):
     agenda_detail = {
         'id': agenda.slug,
-        'slug': agenda.slug, # kept for compatibility
+        'slug': agenda.slug,  # kept for compatibility
         'text': agenda.label,
         'kind': agenda.kind,
         'minimal_booking_delay': agenda.minimal_booking_delay,
@@ -108,21 +114,21 @@ def get_agenda_detail(request, agenda):
     if agenda.kind == 'events':
         agenda_detail['api'] = {
             'datetimes_url': request.build_absolute_uri(
-                reverse('api-agenda-datetimes',
-                        kwargs={'agenda_identifier': agenda.slug}))
+                reverse('api-agenda-datetimes', kwargs={'agenda_identifier': agenda.slug})
+            )
         }
     elif agenda.kind == 'meetings':
         agenda_detail['api'] = {
             'meetings_url': request.build_absolute_uri(
-                reverse('api-agenda-meetings',
-                        kwargs={'agenda_identifier': agenda.slug})),
+                reverse('api-agenda-meetings', kwargs={'agenda_identifier': agenda.slug})
+            ),
             'desks_url': request.build_absolute_uri(
-                reverse('api-agenda-desks',
-                        kwargs={'agenda_identifier': agenda.slug}))
+                reverse('api-agenda-desks', kwargs={'agenda_identifier': agenda.slug})
+            ),
         }
     agenda_detail['api']['fillslots_url'] = request.build_absolute_uri(
-        reverse('api-agenda-fillslots',
-                kwargs={'agenda_identifier': agenda.slug}))
+        reverse('api-agenda-fillslots', kwargs={'agenda_identifier': agenda.slug})
+    )
 
     return agenda_detail
 
@@ -136,7 +142,7 @@ def get_event_places(event):
     if event.waiting_list_places:
         places['waiting_list_total'] = event.waiting_list_places
         places['waiting_list_reserved'] = event.waiting_list
-        places['waiting_list_available'] = (event.waiting_list_places - event.waiting_list)
+        places['waiting_list_available'] = event.waiting_list_places - event.waiting_list
     return places
 
 
@@ -144,10 +150,10 @@ class Agendas(APIView):
     permission_classes = ()
 
     def get(self, request, format=None):
-        agendas = [get_agenda_detail(request, agenda)
-                   for agenda in Agenda.objects.all().order_by('label')]
+        agendas = [get_agenda_detail(request, agenda) for agenda in Agenda.objects.all().order_by('label')]
         return Response({'data': agendas})
 
+
 agendas = Agendas.as_view()
 
 
@@ -155,12 +161,14 @@ class AgendaDetail(APIView):
     '''
     Retrieve an agenda instance.
     '''
+
     permission_classes = ()
 
     def get(self, request, agenda_identifier):
         agenda = get_object_or_404(Agenda, slug=agenda_identifier)
         return Response({'data': get_agenda_detail(request, agenda)})
 
+
 agenda_detail = AgendaDetail.as_view()
 
 
@@ -186,43 +194,68 @@ class Datetimes(APIView):
 
         if agenda.minimal_booking_delay:
             entries = entries.filter(
-                start_datetime__gte=localtime(now() + datetime.timedelta(days=agenda.minimal_booking_delay)).replace(hour=0, minute=0))
+                start_datetime__gte=localtime(
+                    now() + datetime.timedelta(days=agenda.minimal_booking_delay)
+                ).replace(hour=0, minute=0)
+            )
 
         if agenda.maximal_booking_delay:
             entries = entries.filter(
-                start_datetime__lt=localtime(now() + datetime.timedelta(days=agenda.maximal_booking_delay)).replace(hour=0, minute=0))
+                start_datetime__lt=localtime(
+                    now() + datetime.timedelta(days=agenda.maximal_booking_delay)
+                ).replace(hour=0, minute=0)
+            )
 
         if 'date_start' in request.GET:
-            entries = entries.filter(start_datetime__gte=make_aware(
-                datetime.datetime.combine(parse_date(request.GET['date_start']), datetime.time(0, 0))))
+            entries = entries.filter(
+                start_datetime__gte=make_aware(
+                    datetime.datetime.combine(parse_date(request.GET['date_start']), datetime.time(0, 0))
+                )
+            )
 
         if 'date_end' in request.GET:
-            entries = entries.filter(start_datetime__lt=make_aware(
-                datetime.datetime.combine(parse_date(request.GET['date_end']), datetime.time(0, 0))))
-
-        response = {'data': [{'id': x.id,
-                              'slug': x.slug,
-                              'text': force_text(x),
-                              'datetime': format_response_datetime(x.start_datetime),
-                              'description': x.description,
-                              'disabled': bool(x.full),
-                              'api': {
-                                  'fillslot_url': request.build_absolute_uri(
-                                      reverse('api-fillslot',
-                                          kwargs={
-                                              'agenda_identifier': agenda.slug,
-                                              'event_identifier': x.slug or x.id,
-                                      })),
-                                  'status_url': request.build_absolute_uri(
-                                      reverse('api-event-status',
-                                          kwargs={
-                                              'agenda_identifier': agenda.slug,
-                                              'event_identifier': x.slug or x.id,
-                                      }))
-                                  },
-                              } for x in entries]}
+            entries = entries.filter(
+                start_datetime__lt=make_aware(
+                    datetime.datetime.combine(parse_date(request.GET['date_end']), datetime.time(0, 0))
+                )
+            )
+
+        response = {
+            'data': [
+                {
+                    'id': x.id,
+                    'slug': x.slug,
+                    'text': force_text(x),
+                    'datetime': format_response_datetime(x.start_datetime),
+                    'description': x.description,
+                    'disabled': bool(x.full),
+                    'api': {
+                        'fillslot_url': request.build_absolute_uri(
+                            reverse(
+                                'api-fillslot',
+                                kwargs={
+                                    'agenda_identifier': agenda.slug,
+                                    'event_identifier': x.slug or x.id,
+                                },
+                            )
+                        ),
+                        'status_url': request.build_absolute_uri(
+                            reverse(
+                                'api-event-status',
+                                kwargs={
+                                    'agenda_identifier': agenda.slug,
+                                    'event_identifier': x.slug or x.id,
+                                },
+                            )
+                        ),
+                    },
+                }
+                for x in entries
+            ]
+        }
         return Response(response)
 
+
 datetimes = Datetimes.as_view()
 
 
@@ -235,8 +268,9 @@ class MeetingDatetimes(APIView):
                 # legacy access by meeting id
                 meeting_type = MeetingType.objects.get(id=meeting_identifier)
             else:
-                meeting_type = MeetingType.objects.get(slug=meeting_identifier,
-                        agenda__slug=agenda_identifier)
+                meeting_type = MeetingType.objects.get(
+                    slug=meeting_identifier, agenda__slug=agenda_identifier
+                )
         except (ValueError, MeetingType.DoesNotExist):
             raise Http404()
 
@@ -259,22 +293,27 @@ class MeetingDatetimes(APIView):
         # to request.build_absolute_uri()
         fake_event_identifier = '__event_identifier__'
         fillslot_url = request.build_absolute_uri(
-                reverse('api-fillslot',
-                    kwargs={
-                        'agenda_identifier': agenda.slug,
-                        'event_identifier': fake_event_identifier,
-                        }))
-
-        response = {'data': [{'id': x.id,
-                              'datetime': format_response_datetime(x.start_datetime),
-                              'text': force_text(x),
-                              'disabled': bool(x.full),
-                              'api': {
-                                'fillslot_url': fillslot_url.replace(fake_event_identifier, str(x.id)),
-                              },
-                             } for x in slots]}
+            reverse(
+                'api-fillslot',
+                kwargs={'agenda_identifier': agenda.slug, 'event_identifier': fake_event_identifier,},
+            )
+        )
+
+        response = {
+            'data': [
+                {
+                    'id': x.id,
+                    'datetime': format_response_datetime(x.start_datetime),
+                    'text': force_text(x),
+                    'disabled': bool(x.full),
+                    'api': {'fillslot_url': fillslot_url.replace(fake_event_identifier, str(x.id)),},
+                }
+                for x in slots
+            ]
+        }
         return Response(response)
 
+
 meeting_datetimes = MeetingDatetimes.as_view()
 
 
@@ -291,20 +330,28 @@ class MeetingList(APIView):
 
         meeting_types = []
         for meeting_type in agenda.meetingtype_set.all():
-            meeting_types.append({
-                'text': meeting_type.label,
-                'id': meeting_type.slug,
-                'duration': meeting_type.duration,
-                'api': {
-                    'datetimes_url': request.build_absolute_uri(
-                        reverse('api-agenda-meeting-datetimes',
-                            kwargs={'agenda_identifier': agenda.slug,
-                                    'meeting_identifier': meeting_type.slug})),
-                            }
-                })
+            meeting_types.append(
+                {
+                    'text': meeting_type.label,
+                    'id': meeting_type.slug,
+                    'duration': meeting_type.duration,
+                    'api': {
+                        'datetimes_url': request.build_absolute_uri(
+                            reverse(
+                                'api-agenda-meeting-datetimes',
+                                kwargs={
+                                    'agenda_identifier': agenda.slug,
+                                    'meeting_identifier': meeting_type.slug,
+                                },
+                            )
+                        ),
+                    },
+                }
+            )
 
         return Response({'data': meeting_types})
 
+
 meeting_list = MeetingList.as_view()
 
 
@@ -322,6 +369,7 @@ class AgendaDeskList(APIView):
         desks = [{'id': x.slug, 'text': x.label} for x in agenda.desk_set.all()]
         return Response({'data': desks})
 
+
 agenda_desk_list = AgendaDeskList.as_view()
 
 
@@ -329,6 +377,7 @@ class SlotSerializer(serializers.Serializer):
     '''
     payload to fill one slot. The slot (event id) is in the URL.
     '''
+
     label = serializers.CharField(max_length=250, allow_blank=True)
     user_name = serializers.CharField(max_length=250, allow_blank=True)
     user_display_label = serializers.CharField(max_length=250, allow_blank=True)
@@ -342,8 +391,10 @@ class SlotsSerializer(SlotSerializer):
     payload to fill multiple slots: same as SlotSerializer, but the
     slots list is in the payload.
     '''
-    slots = serializers.ListField(required=True,
-        child=serializers.CharField(max_length=64, allow_blank=False))
+
+    slots = serializers.ListField(
+        required=True, child=serializers.CharField(max_length=64, allow_blank=False)
+    )
 
 
 class Fillslots(APIView):
@@ -351,8 +402,7 @@ class Fillslots(APIView):
     serializer_class = SlotsSerializer
 
     def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
-        return self.fillslot(request=request, agenda_identifier=agenda_identifier,
-                             format=format)
+        return self.fillslot(request=request, agenda_identifier=agenda_identifier, format=format)
 
     def fillslot(self, request, agenda_identifier=None, slots=[], format=None):
         multiple_booking = bool(not slots)
@@ -367,22 +417,28 @@ class Fillslots(APIView):
 
         serializer = self.serializer_class(data=request.data, partial=True)
         if not serializer.is_valid():
-            return Response({
-                'err': 1,
-                'err_class': 'invalid payload',
-                'err_desc': _('invalid payload'),
-                'errors': serializer.errors
-            }, status=status.HTTP_400_BAD_REQUEST)
+            return Response(
+                {
+                    'err': 1,
+                    'err_class': 'invalid payload',
+                    'err_desc': _('invalid payload'),
+                    'errors': serializer.errors,
+                },
+                status=status.HTTP_400_BAD_REQUEST,
+            )
         payload = serializer.validated_data
 
         if 'slots' in payload:
             slots = payload['slots']
         if not slots:
-            return Response({
-                'err': 1,
-                'err_class': 'slots list cannot be empty',
-                'err_desc': _('slots list cannot be empty'),
-            }, status=status.HTTP_400_BAD_REQUEST)
+            return Response(
+                {
+                    'err': 1,
+                    'err_class': 'slots list cannot be empty',
+                    'err_desc': _('slots list cannot be empty'),
+                },
+                status=status.HTTP_400_BAD_REQUEST,
+            )
 
         if 'count' in payload:
             places_count = payload['count']
@@ -391,20 +447,26 @@ class Fillslots(APIView):
             try:
                 places_count = int(request.query_params['count'])
             except ValueError:
-                return Response({
-                    'err': 1,
-                    'err_class': 'invalid value for count (%s)' % request.query_params['count'],
-                    'err_desc': _('invalid value for count (%s)') % request.query_params['count'],
-                }, status=status.HTTP_400_BAD_REQUEST)
+                return Response(
+                    {
+                        'err': 1,
+                        'err_class': 'invalid value for count (%s)' % request.query_params['count'],
+                        'err_desc': _('invalid value for count (%s)') % request.query_params['count'],
+                    },
+                    status=status.HTTP_400_BAD_REQUEST,
+                )
         else:
             places_count = 1
 
         if places_count <= 0:
-            return Response({
-                'err': 1,
-                'err_class': 'count cannot be less than or equal to zero',
-                'err_desc': _('count cannot be less than or equal to zero'),
-            }, status=status.HTTP_400_BAD_REQUEST)
+            return Response(
+                {
+                    'err': 1,
+                    'err_class': 'count cannot be less than or equal to zero',
+                    'err_desc': _('count cannot be less than or equal to zero'),
+                },
+                status=status.HTTP_400_BAD_REQUEST,
+            )
 
         to_cancel_booking = None
         cancel_booking_id = None
@@ -412,11 +474,14 @@ class Fillslots(APIView):
             try:
                 cancel_booking_id = int(payload.get('cancel_booking_id'))
             except (ValueError, TypeError):
-                return Response({
-                    'err': 1,
-                    'err_class': 'cancel_booking_id is not an integer',
-                    'err_desc': _('cancel_booking_id is not an integer'),
-                }, status=status.HTTP_400_BAD_REQUEST)
+                return Response(
+                    {
+                        'err': 1,
+                        'err_class': 'cancel_booking_id is not an integer',
+                        'err_desc': _('cancel_booking_id is not an integer'),
+                    },
+                    status=status.HTTP_400_BAD_REQUEST,
+                )
 
         if cancel_booking_id is not None:
             cancel_error = None
@@ -432,11 +497,7 @@ class Fillslots(APIView):
                 cancel_error = gettext_noop('cancel booking: booking does no exist')
 
             if cancel_error:
-                return Response({
-                    'err': 1,
-                    'err_class': cancel_error,
-                    'err_desc': _(cancel_error),
-                })
+                return Response({'err': 1, 'err_class': cancel_error, 'err_desc': _(cancel_error),})
 
         extra_data = {}
         for k, v in request.data.items():
@@ -454,17 +515,25 @@ class Fillslots(APIView):
                 try:
                     meeting_type_id_, datetime_str = slot.split(':')
                 except ValueError:
-                    return Response({
-                        'err': 1,
-                        'err_class': 'invalid slot: %s' % slot,
-                        'err_desc': _('invalid slot: %s') % slot,
-                    }, status=status.HTTP_400_BAD_REQUEST)
+                    return Response(
+                        {
+                            'err': 1,
+                            'err_class': 'invalid slot: %s' % slot,
+                            'err_desc': _('invalid slot: %s') % slot,
+                        },
+                        status=status.HTTP_400_BAD_REQUEST,
+                    )
                 if meeting_type_id_ != meeting_type_id:
-                    return Response({
-                        'err': 1,
-                        'err_class': 'all slots must have the same meeting type id (%s)' % meeting_type_id,
-                        'err_desc': _('all slots must have the same meeting type id (%s)') % meeting_type_id,
-                    }, status=status.HTTP_400_BAD_REQUEST)
+                    return Response(
+                        {
+                            'err': 1,
+                            'err_class': 'all slots must have the same meeting type id (%s)'
+                            % meeting_type_id,
+                            'err_desc': _('all slots must have the same meeting type id (%s)')
+                            % meeting_type_id,
+                        },
+                        status=status.HTTP_400_BAD_REQUEST,
+                    )
                 datetimes.add(make_aware(datetime.datetime.strptime(datetime_str, '%Y-%m-%d-%H%M')))
 
             # get all free slots and separate them by desk
@@ -480,11 +549,13 @@ class Fillslots(APIView):
                     available_desk = Desk.objects.get(id=available_desk_id)
                     break
             else:
-                return Response({
-                    'err': 1,
-                    'err_class': 'no more desk available',
-                    'err_desc': _('no more desk available'),
-                })
+                return Response(
+                    {
+                        'err': 1,
+                        'err_class': 'no more desk available',
+                        'err_desc': _('no more desk available'),
+                    }
+                )
 
             # all datetimes are free, book them in order
             datetimes = list(datetimes)
@@ -494,11 +565,16 @@ class Fillslots(APIView):
             # create them now, with data from the slots and the desk we found.
             events = []
             for start_datetime in datetimes:
-                events.append(Event.objects.create(agenda=agenda,
+                events.append(
+                    Event.objects.create(
+                        agenda=agenda,
                         meeting_type_id=meeting_type_id,
                         start_datetime=start_datetime,
-                        full=False, places=1,
-                        desk=available_desk))
+                        full=False,
+                        places=1,
+                        desk=available_desk,
+                    )
+                )
         else:
             try:
                 events = Event.objects.filter(id__in=[int(s) for s in slots]).order_by('start_datetime')
@@ -514,18 +590,10 @@ class Fillslots(APIView):
                     # in the waiting list.
                     in_waiting_list = True
                     if (event.waiting_list + places_count) > event.waiting_list_places:
-                        return Response({
-                            'err': 1,
-                            'err_class': 'sold out',
-                            'err_desc': _('sold out'),
-                        })
+                        return Response({'err': 1, 'err_class': 'sold out', 'err_desc': _('sold out'),})
             else:
                 if (event.booked_places + places_count) > event.places:
-                    return Response({
-                        'err': 1,
-                        'err_class': 'sold out',
-                        'err_desc': _('sold out')
-                    })
+                    return Response({'err': 1, 'err_class': 'sold out', 'err_desc': _('sold out')})
 
         with transaction.atomic():
             if to_cancel_booking:
@@ -536,13 +604,15 @@ class Fillslots(APIView):
             primary_booking = None
             for event in events:
                 for i in range(places_count):
-                    new_booking = Booking(event_id=event.id,
-                                          in_waiting_list=in_waiting_list,
-                                          label=payload.get('label', ''),
-                                          user_name=payload.get('user_name', ''),
-                                          backoffice_url=payload.get('backoffice_url', ''),
-                                          user_display_label=payload.get('user_display_label', ''),
-                                          extra_data=extra_data)
+                    new_booking = Booking(
+                        event_id=event.id,
+                        in_waiting_list=in_waiting_list,
+                        label=payload.get('label', ''),
+                        user_name=payload.get('user_name', ''),
+                        backoffice_url=payload.get('backoffice_url', ''),
+                        user_display_label=payload.get('user_display_label', ''),
+                        extra_data=extra_data,
+                    )
                     if primary_booking is not None:
                         new_booking.primary_booking = primary_booking
                     new_booking.save()
@@ -556,21 +626,22 @@ class Fillslots(APIView):
             'datetime': format_response_datetime(events[0].start_datetime),
             'api': {
                 'cancel_url': request.build_absolute_uri(
-                    reverse('api-cancel-booking', kwargs={'booking_pk': primary_booking.id})),
+                    reverse('api-cancel-booking', kwargs={'booking_pk': primary_booking.id})
+                ),
                 'ics_url': request.build_absolute_uri(
-                    reverse('api-booking-ics', kwargs={'booking_pk': primary_booking.id})),
-            }
+                    reverse('api-booking-ics', kwargs={'booking_pk': primary_booking.id})
+                ),
+            },
         }
         if in_waiting_list:
             response['api']['accept_url'] = request.build_absolute_uri(
-                    reverse('api-accept-booking', kwargs={'booking_pk': primary_booking.id}))
+                reverse('api-accept-booking', kwargs={'booking_pk': primary_booking.id})
+            )
         if agenda.kind == 'meetings':
             response['end_datetime'] = format_response_datetime(events[-1].end_datetime)
             response['duration'] = (events[-1].end_datetime - events[-1].start_datetime).seconds // 60
         if available_desk:
-            response['desk'] = {
-                'label': available_desk.label,
-                'slug': available_desk.slug}
+            response['desk'] = {'label': available_desk.label, 'slug': available_desk.slug}
         if to_cancel_booking:
             response['cancelled_booking_id'] = cancelled_booking_id
         if agenda.kind == 'events' and not multiple_booking:
@@ -579,6 +650,7 @@ class Fillslots(APIView):
 
         return Response(response)
 
+
 fillslots = Fillslots.as_view()
 
 
@@ -586,10 +658,13 @@ class Fillslot(Fillslots):
     serializer_class = SlotSerializer
 
     def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
-        return self.fillslot(request=request,
-                             agenda_identifier=agenda_identifier,
-                             slots=[event_identifier],  # fill a "list on one slot"
-                             format=format)
+        return self.fillslot(
+            request=request,
+            agenda_identifier=agenda_identifier,
+            slots=[event_identifier],  # fill a "list on one slot"
+            format=format,
+        )
+
 
 fillslot = Fillslot.as_view()
 
@@ -599,14 +674,14 @@ class BookingAPI(APIView):
 
     def initial(self, request, *args, **kwargs):
         super(BookingAPI, self).initial(request, *args, **kwargs)
-        self.booking = Booking.objects.get(id=kwargs.get('booking_pk'),
-                cancellation_datetime__isnull=True)
+        self.booking = Booking.objects.get(id=kwargs.get('booking_pk'), cancellation_datetime__isnull=True)
 
     def delete(self, request, *args, **kwargs):
         self.booking.cancel()
         response = {'err': 0, 'booking_id': self.booking.id}
         return Response(response)
 
+
 booking = BookingAPI.as_view()
 
 
@@ -616,6 +691,7 @@ class CancelBooking(APIView):
 
     It will return an error (code 1) if the booking was already cancelled.
     '''
+
     permission_classes = (permissions.IsAuthenticated,)
 
     def post(self, request, booking_pk=None, format=None):
@@ -631,6 +707,7 @@ class CancelBooking(APIView):
         response = {'err': 0, 'booking_id': booking.id}
         return Response(response)
 
+
 cancel_booking = CancelBooking.as_view()
 
 
@@ -641,6 +718,7 @@ class AcceptBooking(APIView):
     It will return error codes if the booking was cancelled before (code 1) and
     if the booking was not in waiting list (code 2).
     '''
+
     permission_classes = (permissions.IsAuthenticated,)
 
     def post(self, request, booking_pk=None, format=None):
@@ -663,6 +741,7 @@ class AcceptBooking(APIView):
         response = {'err': 0, 'booking_id': booking.id}
         return Response(response)
 
+
 accept_booking = AcceptBooking.as_view()
 
 
@@ -699,4 +778,5 @@ class BookingICS(APIView):
         response = HttpResponse(booking.get_ics(request), content_type='text/calendar')
         return response
 
+
 booking_ics = BookingICS.as_view()
diff --git a/chrono/interval.py b/chrono/interval.py
index 8ff5ddf..5b990bc 100644
--- a/chrono/interval.py
+++ b/chrono/interval.py
@@ -63,6 +63,7 @@ class Intervals(object):
          10: [a],
        }
        '''
+
     def __init__(self):
         self.points = []
         self.container = []
diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py
index 3f049d8..db023ee 100644
--- a/chrono/manager/forms.py
+++ b/chrono/manager/forms.py
@@ -26,16 +26,22 @@ from django.utils.encoding import force_text
 from django.utils.timezone import make_aware
 from django.utils.translation import ugettext_lazy as _
 
-from chrono.agendas.models import (Agenda, Event, MeetingType, TimePeriod, Desk,
-                                   TimePeriodException, WEEKDAYS_LIST)
+from chrono.agendas.models import (
+    WEEKDAYS_LIST,
+    Agenda,
+    Desk,
+    Event,
+    MeetingType,
+    TimePeriod,
+    TimePeriodException,
+)
 
 from . import widgets
 
-
 DATETIME_OPTIONS = {
-        'weekStart': 1,
-        'autoclose': True,
-        }
+    'weekStart': 1,
+    'autoclose': True,
+}
 
 
 class DateTimeWidget(widgets.DateTimeWidget):
@@ -49,11 +55,11 @@ class AgendaAddForm(forms.ModelForm):
         fields = ['label', 'kind', 'edit_role', 'view_role']
 
     edit_role = forms.ModelChoiceField(
-            label=_('Edit Role'), required=False,
-            queryset=Group.objects.all().order_by('name'))
+        label=_('Edit Role'), required=False, queryset=Group.objects.all().order_by('name')
+    )
     view_role = forms.ModelChoiceField(
-            label=_('View Role'), required=False,
-            queryset=Group.objects.all().order_by('name'))
+        label=_('View Role'), required=False, queryset=Group.objects.all().order_by('name')
+    )
 
 
 class AgendaEditForm(AgendaAddForm):
@@ -66,8 +72,8 @@ class NewEventForm(forms.ModelForm):
     class Meta:
         model = Event
         widgets = {
-                'agenda': forms.HiddenInput(),
-                'start_datetime': DateTimeWidget(),
+            'agenda': forms.HiddenInput(),
+            'start_datetime': DateTimeWidget(),
         }
         exclude = ['full', 'meeting_type', 'desk', 'slug']
 
@@ -76,8 +82,8 @@ class EventForm(forms.ModelForm):
     class Meta:
         model = Event
         widgets = {
-                'agenda': forms.HiddenInput(),
-                'start_datetime': DateTimeWidget(),
+            'agenda': forms.HiddenInput(),
+            'start_datetime': DateTimeWidget(),
         }
         exclude = ['full', 'meeting_type', 'desk']
 
@@ -86,7 +92,7 @@ class NewMeetingTypeForm(forms.ModelForm):
     class Meta:
         model = MeetingType
         widgets = {
-                'agenda': forms.HiddenInput(),
+            'agenda': forms.HiddenInput(),
         }
         exclude = ['slug']
 
@@ -95,16 +101,15 @@ class MeetingTypeForm(forms.ModelForm):
     class Meta:
         model = MeetingType
         widgets = {
-                'agenda': forms.HiddenInput(),
+            'agenda': forms.HiddenInput(),
         }
         exclude = []
 
 
 class TimePeriodAddForm(forms.Form):
     weekdays = forms.MultipleChoiceField(
-            label=_('Days'),
-            widget=widgets.WeekdaysWidget(),
-            choices=WEEKDAYS_LIST)
+        label=_('Days'), widget=widgets.WeekdaysWidget(), choices=WEEKDAYS_LIST
+    )
     start_time = forms.TimeField(label=_('Start Time'), widget=widgets.TimeWidget())
     end_time = forms.TimeField(label=_('End Time'), widget=widgets.TimeWidget())
 
@@ -118,9 +123,9 @@ class TimePeriodForm(forms.ModelForm):
     class Meta:
         model = TimePeriod
         widgets = {
-                'start_time': widgets.TimeWidget(),
-                'end_time': widgets.TimeWidget(),
-                'desk': forms.HiddenInput(),
+            'start_time': widgets.TimeWidget(),
+            'end_time': widgets.TimeWidget(),
+            'desk': forms.HiddenInput(),
         }
         exclude = []
 
@@ -166,11 +171,14 @@ class TimePeriodExceptionForm(forms.ModelForm):
 
 class ImportEventsForm(forms.Form):
     events_csv_file = forms.FileField(
-            label=_('Events File'),
-            required=True,
-            help_text=_('CSV file with date, time, number of places, '
-                        'number of places in waiting list, and label '
-                        'as columns.'))
+        label=_('Events File'),
+        required=True,
+        help_text=_(
+            'CSV file with date, time, number of places, '
+            'number of places in waiting list, and label '
+            'as columns.'
+        ),
+    )
     events = None
 
     def __init__(self, agenda_pk, **kwargs):
@@ -201,31 +209,37 @@ class ImportEventsForm(forms.Form):
             if not csvline:
                 continue
             if len(csvline) < 3:
-                raise ValidationError(_('Invalid file format. (line %d)') % (i+1))
+                raise ValidationError(_('Invalid file format. (line %d)') % (i + 1))
             if i == 0 and csvline[0].strip('#') in ('date', 'Date', _('date'), _('Date')):
                 continue
             event = Event()
             event.agenda_id = self.agenda_pk
-            for datetime_fmt in ('%Y-%m-%d %H:%M', '%d/%m/%Y %H:%M',
-                    '%d/%m/%Y %Hh%M', '%Y-%m-%d %H:%M:%S', '%d/%m/%Y %H:%M:%S'):
+            for datetime_fmt in (
+                '%Y-%m-%d %H:%M',
+                '%d/%m/%Y %H:%M',
+                '%d/%m/%Y %Hh%M',
+                '%Y-%m-%d %H:%M:%S',
+                '%d/%m/%Y %H:%M:%S',
+            ):
                 try:
-                    event_datetime = datetime.datetime.strptime(
-                            '%s %s' % tuple(csvline[:2]), datetime_fmt)
+                    event_datetime = datetime.datetime.strptime('%s %s' % tuple(csvline[:2]), datetime_fmt)
                 except ValueError:
                     continue
                 event.start_datetime = make_aware(event_datetime)
                 break
             else:
-                raise ValidationError(_('Invalid file format. (date/time format, line %d)') % (i+1))
+                raise ValidationError(_('Invalid file format. (date/time format, line %d)') % (i + 1))
             try:
                 event.places = int(csvline[2])
             except ValueError:
-                raise ValidationError(_('Invalid file format. (number of places, line %d)') % (i+1))
+                raise ValidationError(_('Invalid file format. (number of places, line %d)') % (i + 1))
             if len(csvline) >= 4:
                 try:
                     event.waiting_list_places = int(csvline[3])
                 except ValueError:
-                    raise ValidationError(_('Invalid file format. (number of places in waiting list, line %d)') % (i+1))
+                    raise ValidationError(
+                        _('Invalid file format. (number of places in waiting list, line %d)') % (i + 1)
+                    )
             if len(csvline) >= 5:
                 event.label = force_text(csvline[4])
             exclude = ['desk', 'meeting_type']
@@ -237,11 +251,10 @@ class ImportEventsForm(forms.Form):
                 event.full_clean(exclude=exclude)
             except ValidationError as e:
                 errors = [
-                    _('Invalid file format. (%(label)s: %(errors)s, line %(line)d)') % {
-                        'label': label,
-                        'errors': u', '.join(field_errors),
-                        'line': i + 1
-                    } for label, field_errors in e.message_dict.items()]
+                    _('Invalid file format. (%(label)s: %(errors)s, line %(line)d)')
+                    % {'label': label, 'errors': u', '.join(field_errors), 'line': i + 1}
+                    for label, field_errors in e.message_dict.items()
+                ]
                 raise ValidationError(errors)
             events.append(event)
         self.events = events
@@ -252,10 +265,16 @@ class ExceptionsImportForm(forms.ModelForm):
         model = Desk
         fields = []
 
-    ics_file = forms.FileField(label=_('ICS File'), required=False,
-            help_text=_('ICS file containing events which will be considered as exceptions.'))
-    ics_url = forms.URLField(label=_('URL'), required=False,
-            help_text=_('URL to remote calendar which will be synchronised hourly.'))
+    ics_file = forms.FileField(
+        label=_('ICS File'),
+        required=False,
+        help_text=_('ICS file containing events which will be considered as exceptions.'),
+    )
+    ics_url = forms.URLField(
+        label=_('URL'),
+        required=False,
+        help_text=_('URL to remote calendar which will be synchronised hourly.'),
+    )
 
 
 class AgendasImportForm(forms.Form):
diff --git a/chrono/manager/management/commands/export_site.py b/chrono/manager/management/commands/export_site.py
index 9ac15cb..1751b78 100644
--- a/chrono/manager/management/commands/export_site.py
+++ b/chrono/manager/management/commands/export_site.py
@@ -27,8 +27,8 @@ class Command(BaseCommand):
 
     def add_arguments(self, parser):
         parser.add_argument(
-                '--output', metavar='FILE', default=None,
-                help='name of a file to write output to')
+            '--output', metavar='FILE', default=None, help='name of a file to write output to'
+        )
 
     def handle(self, *args, **options):
         if options['output']:
diff --git a/chrono/manager/management/commands/import_site.py b/chrono/manager/management/commands/import_site.py
index f32a1dd..e56e06c 100644
--- a/chrono/manager/management/commands/import_site.py
+++ b/chrono/manager/management/commands/import_site.py
@@ -27,17 +27,12 @@ class Command(BaseCommand):
     help = 'Import an exported site'
 
     def add_arguments(self, parser):
-        parser.add_argument('filename', metavar='FILENAME', type=str,
-                help='name of file to import')
+        parser.add_argument('filename', metavar='FILENAME', type=str, help='name of file to import')
+        parser.add_argument('--clean', action='store_true', default=False, help='Clean site before importing')
         parser.add_argument(
-                '--clean', action='store_true', default=False,
-                help='Clean site before importing')
-        parser.add_argument(
-                '--if-empty', action='store_true', default=False,
-                help='Import only if site is empty')
-        parser.add_argument(
-                '--overwrite', action='store_true', default=False,
-                help='Overwrite existing data')
+            '--if-empty', action='store_true', default=False, help='Import only if site is empty'
+        )
+        parser.add_argument('--overwrite', action='store_true', default=False, help='Overwrite existing data')
 
     def handle(self, filename, **options):
         if filename == '-':
@@ -45,9 +40,11 @@ class Command(BaseCommand):
         else:
             fd = open(filename)
         try:
-            import_site(json.load(fd),
-                        if_empty=options['if_empty'],
-                        clean=options['clean'],
-                        overwrite=options['overwrite'])
+            import_site(
+                json.load(fd),
+                if_empty=options['if_empty'],
+                clean=options['clean'],
+                overwrite=options['overwrite'],
+            )
         except AgendaImportError as exc:
             raise CommandError(u'%s' % exc)
diff --git a/chrono/manager/urls.py b/chrono/manager/urls.py
index eba7a17..39866c0 100644
--- a/chrono/manager/urls.py
+++ b/chrono/manager/urls.py
@@ -19,70 +19,91 @@ from django.conf.urls import url
 from . import views
 
 urlpatterns = [
-        url(r'^$', views.homepage, name='chrono-manager-homepage'),
-        url(r'^agendas/add/$', views.agenda_add,
-            name='chrono-manager-agenda-add'),
-        url(r'^agendas/import/$', views.agendas_import,
-            name='chrono-manager-agendas-import'),
-        url(r'^agendas/(?P<pk>\d+)/$', views.agenda_view,
-            name='chrono-manager-agenda-view'),
-        url(r'^agendas/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$', views.agenda_monthly_view,
-            name='chrono-manager-agenda-month-view'),
-        url(r'^agendas/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/(?P<day>[0-9]+)/$', views.agenda_day_view,
-            name='chrono-manager-agenda-day-view'),
-        url(r'^agendas/(?P<pk>\d+)/settings$', views.agenda_settings,
-            name='chrono-manager-agenda-settings'),
-        url(r'^agendas/(?P<pk>\d+)/edit$', views.agenda_edit,
-            name='chrono-manager-agenda-edit'),
-        url(r'^agendas/(?P<pk>\d+)/delete$', views.agenda_delete,
-            name='chrono-manager-agenda-delete'),
-        url(r'^agendas/(?P<pk>\d+)/export$', views.agenda_export,
-            name='chrono-manager-agenda-export'),
-        url(r'^agendas/(?P<pk>\d+)/add-event$', views.agenda_add_event,
-            name='chrono-manager-agenda-add-event'),
-        url(r'^agendas/(?P<pk>\d+)/import-events$', views.agenda_import_events,
-            name='chrono-manager-agenda-import-events'),
-        url(r'^events/(?P<pk>\d+)/$', views.event_edit,
-            name='chrono-manager-event-edit'),
-        url(r'^events/(?P<pk>\d+)/delete$', views.event_delete,
-            name='chrono-manager-event-delete'),
-
-        url(r'^agendas/(?P<pk>\d+)/add-meeting-type$', views.agenda_add_meeting_type,
-            name='chrono-manager-agenda-add-meeting-type'),
-        url(r'^meetingtypes/(?P<pk>\d+)/edit$', views.meeting_type_edit,
-            name='chrono-manager-meeting-type-edit'),
-        url(r'^meetingtypes/(?P<pk>\d+)/delete$', views.meeting_type_delete,
-            name='chrono-manager-meeting-type-delete'),
-
-        url(r'^agendas/(?P<agenda_pk>\d+)/desk/(?P<pk>\d+)/add-time-period$', views.agenda_add_time_period,
-            name='chrono-manager-agenda-add-time-period'),
-        url(r'^timeperiods/(?P<pk>\d+)/edit$', views.time_period_edit,
-            name='chrono-manager-time-period-edit'),
-        url(r'^timeperiods/(?P<pk>\d+)/delete$', views.time_period_delete,
-            name='chrono-manager-time-period-delete'),
-
-        url(r'^agendas/(?P<pk>\d+)/add-desk$', views.agenda_add_desk,
-            name='chrono-manager-agenda-add-desk'),
-        url(r'^desks/(?P<pk>\d+)/edit$', views.desk_edit,
-            name='chrono-manager-desk-edit'),
-        url(r'^desks/(?P<pk>\d+)/delete$', views.desk_delete,
-            name='chrono-manager-desk-delete'),
-
-        url(r'^agendas/(?P<agenda_pk>\d+)/desk/(?P<pk>\d+)/add-time-period-exception$', views.agenda_add_time_period_exception,
-            name='chrono-manager-agenda-add-time-period-exception'),
-        url(r'^agendas/desk/(?P<pk>\d+)/import-exceptions-from-ics/$', views.desk_import_time_period_exceptions,
-            name='chrono-manager-desk-add-import-time-period-exceptions'),
-        url(r'^time-period-exceptions/(?P<pk>\d+)/edit$', views.time_period_exception_edit,
-            name='chrono-manager-time-period-exception-edit'),
-        url(r'^time-period-exceptions/(?P<pk>\d+)/delete$', views.time_period_exception_delete,
-            name='chrono-manager-time-period-exception-delete'),
-        url(r'^time-period-exceptions/(?P<pk>\d+)/exception-extract-list$', views.time_period_exception_extract_list,
-            name='chrono-manager-time-period-exception-extract-list'),
-        url(r'^time-period-exceptions/(?P<pk>\d+)/exception-list$', views.time_period_exception_list,
-            name='chrono-manager-time-period-exception-list'),
-
-        url(r'^agendas/events.csv$', views.agenda_import_events_sample_csv,
-            name='chrono-manager-sample-events-csv'),
-
-        url(r'^menu.json$', views.menu_json),
+    url(r'^$', views.homepage, name='chrono-manager-homepage'),
+    url(r'^agendas/add/$', views.agenda_add, name='chrono-manager-agenda-add'),
+    url(r'^agendas/import/$', views.agendas_import, name='chrono-manager-agendas-import'),
+    url(r'^agendas/(?P<pk>\d+)/$', views.agenda_view, name='chrono-manager-agenda-view'),
+    url(
+        r'^agendas/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$',
+        views.agenda_monthly_view,
+        name='chrono-manager-agenda-month-view',
+    ),
+    url(
+        r'^agendas/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/(?P<day>[0-9]+)/$',
+        views.agenda_day_view,
+        name='chrono-manager-agenda-day-view',
+    ),
+    url(r'^agendas/(?P<pk>\d+)/settings$', views.agenda_settings, name='chrono-manager-agenda-settings'),
+    url(r'^agendas/(?P<pk>\d+)/edit$', views.agenda_edit, name='chrono-manager-agenda-edit'),
+    url(r'^agendas/(?P<pk>\d+)/delete$', views.agenda_delete, name='chrono-manager-agenda-delete'),
+    url(r'^agendas/(?P<pk>\d+)/export$', views.agenda_export, name='chrono-manager-agenda-export'),
+    url(r'^agendas/(?P<pk>\d+)/add-event$', views.agenda_add_event, name='chrono-manager-agenda-add-event'),
+    url(
+        r'^agendas/(?P<pk>\d+)/import-events$',
+        views.agenda_import_events,
+        name='chrono-manager-agenda-import-events',
+    ),
+    url(r'^events/(?P<pk>\d+)/$', views.event_edit, name='chrono-manager-event-edit'),
+    url(r'^events/(?P<pk>\d+)/delete$', views.event_delete, name='chrono-manager-event-delete'),
+    url(
+        r'^agendas/(?P<pk>\d+)/add-meeting-type$',
+        views.agenda_add_meeting_type,
+        name='chrono-manager-agenda-add-meeting-type',
+    ),
+    url(r'^meetingtypes/(?P<pk>\d+)/edit$', views.meeting_type_edit, name='chrono-manager-meeting-type-edit'),
+    url(
+        r'^meetingtypes/(?P<pk>\d+)/delete$',
+        views.meeting_type_delete,
+        name='chrono-manager-meeting-type-delete',
+    ),
+    url(
+        r'^agendas/(?P<agenda_pk>\d+)/desk/(?P<pk>\d+)/add-time-period$',
+        views.agenda_add_time_period,
+        name='chrono-manager-agenda-add-time-period',
+    ),
+    url(r'^timeperiods/(?P<pk>\d+)/edit$', views.time_period_edit, name='chrono-manager-time-period-edit'),
+    url(
+        r'^timeperiods/(?P<pk>\d+)/delete$',
+        views.time_period_delete,
+        name='chrono-manager-time-period-delete',
+    ),
+    url(r'^agendas/(?P<pk>\d+)/add-desk$', views.agenda_add_desk, name='chrono-manager-agenda-add-desk'),
+    url(r'^desks/(?P<pk>\d+)/edit$', views.desk_edit, name='chrono-manager-desk-edit'),
+    url(r'^desks/(?P<pk>\d+)/delete$', views.desk_delete, name='chrono-manager-desk-delete'),
+    url(
+        r'^agendas/(?P<agenda_pk>\d+)/desk/(?P<pk>\d+)/add-time-period-exception$',
+        views.agenda_add_time_period_exception,
+        name='chrono-manager-agenda-add-time-period-exception',
+    ),
+    url(
+        r'^agendas/desk/(?P<pk>\d+)/import-exceptions-from-ics/$',
+        views.desk_import_time_period_exceptions,
+        name='chrono-manager-desk-add-import-time-period-exceptions',
+    ),
+    url(
+        r'^time-period-exceptions/(?P<pk>\d+)/edit$',
+        views.time_period_exception_edit,
+        name='chrono-manager-time-period-exception-edit',
+    ),
+    url(
+        r'^time-period-exceptions/(?P<pk>\d+)/delete$',
+        views.time_period_exception_delete,
+        name='chrono-manager-time-period-exception-delete',
+    ),
+    url(
+        r'^time-period-exceptions/(?P<pk>\d+)/exception-extract-list$',
+        views.time_period_exception_extract_list,
+        name='chrono-manager-time-period-exception-extract-list',
+    ),
+    url(
+        r'^time-period-exceptions/(?P<pk>\d+)/exception-list$',
+        views.time_period_exception_list,
+        name='chrono-manager-time-period-exception-list',
+    ),
+    url(
+        r'^agendas/events.csv$',
+        views.agenda_import_events_sample_csv,
+        name='chrono-manager-sample-events-csv',
+    ),
+    url(r'^menu.json$', views.menu_json),
 ]
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index 336f57d..9320710 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -20,25 +20,54 @@ import json
 from django.contrib import messages
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
-from django.http import HttpResponse, Http404, HttpResponseRedirect
+from django.http import Http404, HttpResponse, HttpResponseRedirect
 from django.shortcuts import get_object_or_404
 from django.urls import reverse, reverse_lazy
 from django.utils.dates import MONTHS
-from django.utils.timezone import now, make_aware, make_naive
+from django.utils.encoding import force_text
+from django.utils.timezone import make_aware, make_naive, now
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ungettext
-from django.utils.encoding import force_text
-from django.views.generic import (DetailView, CreateView, UpdateView,
-        ListView, DeleteView, FormView, TemplateView, DayArchiveView,
-        MonthArchiveView)
-
-from chrono.agendas.models import (Agenda, Event, MeetingType, TimePeriod,
-                                   Booking, Desk, TimePeriodException,
-                                   ICSError, AgendaImportError)
-
-from .forms import (AgendaAddForm, AgendaEditForm, NewEventForm, EventForm, NewMeetingTypeForm, MeetingTypeForm,
-                    TimePeriodForm, ImportEventsForm, NewDeskForm, DeskForm, TimePeriodExceptionForm,
-                    ExceptionsImportForm, AgendasImportForm, TimePeriodAddForm)
+from django.views.generic import (
+    CreateView,
+    DayArchiveView,
+    DeleteView,
+    DetailView,
+    FormView,
+    ListView,
+    MonthArchiveView,
+    TemplateView,
+    UpdateView,
+)
+
+from chrono.agendas.models import (
+    Agenda,
+    AgendaImportError,
+    Booking,
+    Desk,
+    Event,
+    ICSError,
+    MeetingType,
+    TimePeriod,
+    TimePeriodException,
+)
+
+from .forms import (
+    AgendaAddForm,
+    AgendaEditForm,
+    AgendasImportForm,
+    DeskForm,
+    EventForm,
+    ExceptionsImportForm,
+    ImportEventsForm,
+    MeetingTypeForm,
+    NewDeskForm,
+    NewEventForm,
+    NewMeetingTypeForm,
+    TimePeriodAddForm,
+    TimePeriodExceptionForm,
+    TimePeriodForm,
+)
 from .utils import import_site
 
 
@@ -53,6 +82,7 @@ class HomepageView(ListView):
             queryset = queryset.filter(Q(view_role_id__in=group_ids) | Q(edit_role_id__in=group_ids))
         return queryset
 
+
 homepage = HomepageView.as_view()
 
 
@@ -76,6 +106,7 @@ class AgendaAddView(CreateView):
     def get_success_url(self):
         return reverse('chrono-manager-agenda-settings', kwargs={'pk': self.object.id})
 
+
 agenda_add = AgendaAddView.as_view()
 
 
@@ -108,20 +139,21 @@ class AgendasImportView(FormView):
             if results.get('created') == 0:
                 message1 = _('No agenda created.')
             else:
-                message1 = ungettext('An agenda has been created.',
-                        '%(count)d agendas have been created.', results['created']) % {
-                                'count': results['created']}
+                message1 = ungettext(
+                    'An agenda has been created.', '%(count)d agendas have been created.', results['created']
+                ) % {'count': results['created']}
 
             if results.get('updated') == 0:
                 message2 = _('No agenda updated.')
             else:
-                message2 = ungettext('An agenda has been updated.',
-                        '%(count)d agendas have been updated.', results['updated']) % {
-                                'count': results['updated']}
+                message2 = ungettext(
+                    'An agenda has been updated.', '%(count)d agendas have been updated.', results['updated']
+                ) % {'count': results['updated']}
             messages.info(self.request, u'%s %s' % (message1, message2))
 
         return super(AgendasImportView, self).form_valid(form)
 
+
 agendas_import = AgendasImportView.as_view()
 
 
@@ -139,6 +171,7 @@ class AgendaEditView(UpdateView):
     def get_success_url(self):
         return reverse('chrono-manager-agenda-settings', kwargs={'pk': self.object.id})
 
+
 agenda_edit = AgendaEditView.as_view()
 
 
@@ -155,9 +188,10 @@ class AgendaDeleteView(DeleteView):
     def get_context_data(self, **kwargs):
         context = super(AgendaDeleteView, self).get_context_data(**kwargs)
         context['cannot_delete'] = Booking.objects.filter(
-                event__agenda=self.get_object(),
-                event__start_datetime__gt=now(),
-                cancellation_datetime__isnull=True).exists()
+            event__agenda=self.get_object(),
+            event__start_datetime__gt=now(),
+            cancellation_datetime__isnull=True,
+        ).exists()
         return context
 
     def delete(self, request, *args, **kwargs):
@@ -167,6 +201,7 @@ class AgendaDeleteView(DeleteView):
             raise PermissionDenied()
         return super(AgendaDeleteView, self).delete(request, *args, **kwargs)
 
+
 agenda_delete = AgendaDeleteView.as_view()
 
 
@@ -184,15 +219,16 @@ class AgendaView(DetailView):
         if agenda.kind == 'meetings':
             # redirect to today view
             today = datetime.date.today()
-            return HttpResponseRedirect(reverse('chrono-manager-agenda-day-view',
-                    kwargs={'pk': agenda.id,
-                            'year': today.year,
-                            'month': today.month,
-                            'day': today.day}))
+            return HttpResponseRedirect(
+                reverse(
+                    'chrono-manager-agenda-day-view',
+                    kwargs={'pk': agenda.id, 'year': today.year, 'month': today.month, 'day': today.day},
+                )
+            )
 
         # redirect to settings
-        return HttpResponseRedirect(
-                reverse('chrono-manager-agenda-settings', kwargs={'pk': agenda.id}))
+        return HttpResponseRedirect(reverse('chrono-manager-agenda-settings', kwargs={'pk': agenda.id}))
+
 
 agenda_view = AgendaView.as_view()
 
@@ -214,20 +250,23 @@ class AgendaDateView(object):
         # specify 6am time to get the expected timezone on daylight saving time
         # days.
         try:
-            self.date = make_aware(datetime.datetime.strptime(
-                    '%s-%s-%s 06:00' % (self.get_year(), self.get_month(), self.get_day()),
-                    '%Y-%m-%d %H:%M'))
+            self.date = make_aware(
+                datetime.datetime.strptime(
+                    '%s-%s-%s 06:00' % (self.get_year(), self.get_month(), self.get_day()), '%Y-%m-%d %H:%M'
+                )
+            )
         except ValueError:  # day is out of range for month
             # redirect to last day of month
             date = datetime.date(int(self.get_year()), int(self.get_month()), 1)
             date += datetime.timedelta(days=40)
             date = date.replace(day=1)
             date -= datetime.timedelta(days=1)
-            return HttpResponseRedirect(reverse('chrono-manager-agenda-day-view',
-                    kwargs={'pk': self.agenda.id,
-                            'year': date.year,
-                            'month': date.month,
-                            'day': date.day}))
+            return HttpResponseRedirect(
+                reverse(
+                    'chrono-manager-agenda-day-view',
+                    kwargs={'pk': self.agenda.id, 'year': date.year, 'month': date.month, 'day': date.day},
+                )
+            )
         return super(AgendaDateView, self).dispatch(request, *args, **kwargs)
 
     def get_context_data(self, **kwargs):
@@ -253,7 +292,7 @@ class AgendaDateView(object):
 
     def get_years(self):
         year = now().year
-        return [str(x) for x in range(year-1, year+5)]
+        return [str(x) for x in range(year - 1, year + 5)]
 
 
 class AgendaDayView(AgendaDateView, DayArchiveView):
@@ -261,25 +300,30 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
 
     def get_previous_day_url(self):
         previous_day = self.date.date() - datetime.timedelta(days=1)
-        return reverse('chrono-manager-agenda-day-view',
-                kwargs={'pk': self.agenda.id,
-                        'year': previous_day.year,
-                        'month': previous_day.month,
-                        'day': previous_day.day})
+        return reverse(
+            'chrono-manager-agenda-day-view',
+            kwargs={
+                'pk': self.agenda.id,
+                'year': previous_day.year,
+                'month': previous_day.month,
+                'day': previous_day.day,
+            },
+        )
 
     def get_next_day_url(self):
         next_day = self.date.date() + datetime.timedelta(days=1)
-        return reverse('chrono-manager-agenda-day-view',
-                kwargs={'pk': self.agenda.id,
-                        'year': next_day.year,
-                        'month': next_day.month,
-                        'day': next_day.day})
+        return reverse(
+            'chrono-manager-agenda-day-view',
+            kwargs={
+                'pk': self.agenda.id,
+                'year': next_day.year,
+                'month': next_day.month,
+                'day': next_day.day,
+            },
+        )
 
     def get_timetable_infos(self):
-        timeperiods = TimePeriod.objects.filter(
-                desk__agenda=self.agenda,
-                weekday=self.date.weekday(),
-                )
+        timeperiods = TimePeriod.objects.filter(desk__agenda=self.agenda, weekday=self.date.weekday(),)
         if not timeperiods:
             return
 
@@ -307,15 +351,22 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
                     # use first row to include opening hours
                     info['opening_hours'] = opening_hours = []
                     for opening_hour in desk.get_opening_hours(current_date.date()):
-                        opening_hours.append({
-                            'css_top': 100 * (opening_hour.begin - start_date).seconds // 3600,
-                            'css_height': 100 * (opening_hour.end - opening_hour.begin).seconds // 3600,
-                        })
+                        opening_hours.append(
+                            {
+                                'css_top': 100 * (opening_hour.begin - start_date).seconds // 3600,
+                                'css_height': 100 * (opening_hour.end - opening_hour.begin).seconds // 3600,
+                            }
+                        )
                 infos.append(info)
                 info['bookings'] = bookings = []  # bookings for this desk
                 finish_datetime = current_date + interval
-                for event in [x for x in self.object_list if x.desk_id == desk.id and
-                              x.start_datetime >= current_date and x.start_datetime < finish_datetime]:
+                for event in [
+                    x
+                    for x in self.object_list
+                    if x.desk_id == desk.id
+                    and x.start_datetime >= current_date
+                    and x.start_datetime < finish_datetime
+                ]:
                     # don't consider cancelled bookings
                     for booking in [x for x in event.booking_set.all() if not x.cancellation_datetime]:
                         booking.css_top = int(100 * event.start_datetime.minute / 60)
@@ -326,6 +377,7 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
             current_date += interval
             first = False
 
+
 agenda_day_view = AgendaDayView.as_view()
 
 
@@ -334,17 +386,17 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
 
     def get_previous_month_url(self):
         previous_month = self.get_previous_month(self.date.date())
-        return reverse('chrono-manager-agenda-month-view',
-                kwargs={'pk': self.agenda.id,
-                        'year': previous_month.year,
-                        'month': previous_month.month})
+        return reverse(
+            'chrono-manager-agenda-month-view',
+            kwargs={'pk': self.agenda.id, 'year': previous_month.year, 'month': previous_month.month},
+        )
 
     def get_next_month_url(self):
         next_month = self.get_next_month(self.date.date())
-        return reverse('chrono-manager-agenda-month-view',
-                kwargs={'pk': self.agenda.id,
-                        'year': next_month.year,
-                        'month': next_month.month})
+        return reverse(
+            'chrono-manager-agenda-month-view',
+            kwargs={'pk': self.agenda.id, 'year': next_month.year, 'month': next_month.month},
+        )
 
     def get_day(self):
         return '1'
@@ -362,11 +414,11 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
             last_week_number = 53
 
         for week_number in range(first_week_number, last_week_number + 1):
-            yield self.get_week_timetable_infos(week_number-first_week_number, timeperiods)
+            yield self.get_week_timetable_infos(week_number - first_week_number, timeperiods)
 
     def get_week_timetable_infos(self, week_index, timeperiods):
 
-        date = self.date + datetime.timedelta(week_index*7)
+        date = self.date + datetime.timedelta(week_index * 7)
         year, week_number, dow = date.isocalendar()
         start_date = date - datetime.timedelta(dow)
 
@@ -382,16 +434,23 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
             periods.append(period)
             period = period + interval
 
-        return {'days': [self.get_day_timetable_infos(start_date + datetime.timedelta(i), interval) for i in range(1, 8)],
-                'periods': periods}
+        return {
+            'days': [
+                self.get_day_timetable_infos(start_date + datetime.timedelta(i), interval)
+                for i in range(1, 8)
+            ],
+            'periods': periods,
+        }
 
     def get_day_timetable_infos(self, day, interval):
         day = make_aware(make_naive(day))  # give day correct timezone
         period = current_date = day.replace(hour=self.min_timeperiod.hour, minute=0)
-        timetable = {'date': current_date,
-                     'today': day.date() == datetime.date.today(),
-                     'other_month': day.month != self.date.month,
-                     'infos': {'opening_hours': [], 'booked_slots': []}}
+        timetable = {
+            'date': current_date,
+            'today': day.date() == datetime.date.today(),
+            'other_month': day.month != self.date.month,
+            'infos': {'opening_hours': [], 'booked_slots': []},
+        }
 
         desks = self.agenda.desk_set.all()
         desks_len = len(desks)
@@ -406,35 +465,42 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
             period_end = period + interval
             for desk_index, desk in enumerate(desks):
                 width = (98.0 / desks_len) - 1
-                for event in [x for x in self.object_list if x.desk_id == desk.id and
-                              x.start_datetime >= period and x.start_datetime < period_end]:
+                for event in [
+                    x
+                    for x in self.object_list
+                    if x.desk_id == desk.id and x.start_datetime >= period and x.start_datetime < period_end
+                ]:
                     # don't consider cancelled bookings
                     bookings = [x for x in event.booking_set.all() if not x.cancellation_datetime]
                     if not bookings:
                         continue
-                    booking = {'css_top': 100 * (event.start_datetime - current_date).seconds // 3600,
-                               'css_height': 100 * event.meeting_type.duration // 60,
-                               'css_width': width,
-                               'css_left': left,
-                               'desk': desk,
-                               'booking': bookings[0]
+                    booking = {
+                        'css_top': 100 * (event.start_datetime - current_date).seconds // 3600,
+                        'css_height': 100 * event.meeting_type.duration // 60,
+                        'css_width': width,
+                        'css_left': left,
+                        'desk': desk,
+                        'booking': bookings[0],
                     }
                     timetable['infos']['booked_slots'].append(booking)
 
                 # get desks opening hours on last period iteration
                 if period == max_date:
                     for hour in desk.get_opening_hours(current_date):
-                        timetable['infos']['opening_hours'].append({
-                            'css_top': 100 * (hour.begin - current_date).seconds // 3600,
-                            'css_height': 100 * (hour.end - hour.begin).seconds // 3600,
-                            'css_width': width,
-                            'css_left': left,
-                        })
+                        timetable['infos']['opening_hours'].append(
+                            {
+                                'css_top': 100 * (hour.begin - current_date).seconds // 3600,
+                                'css_height': 100 * (hour.end - hour.begin).seconds // 3600,
+                                'css_width': width,
+                                'css_left': left,
+                            }
+                        )
                 left += width + 1
             period += interval
 
         return timetable
 
+
 agenda_monthly_view = AgendaMonthView.as_view()
 
 
@@ -550,6 +616,7 @@ class AgendaSettings(ManagedAgendaMixin, DetailView):
         context['user_can_manage'] = self.get_object().can_be_managed(self.request.user)
         return context
 
+
 agenda_settings = AgendaSettings.as_view()
 
 
@@ -561,6 +628,7 @@ class AgendaExport(ManagedAgendaMixin, DetailView):
         json.dump({'agendas': [self.get_object().export_json()]}, response, indent=2)
         return response
 
+
 agenda_export = AgendaExport.as_view()
 
 
@@ -569,6 +637,7 @@ class AgendaAddEventView(ManagedAgendaMixin, CreateView):
     model = Event
     form_class = NewEventForm
 
+
 agenda_add_event = AgendaAddEventView.as_view()
 
 
@@ -583,6 +652,7 @@ class AgendaImportEventsSampleView(TemplateView):
         context['some_future_date'] = some_future_date
         return context
 
+
 agenda_import_events_sample_csv = AgendaImportEventsSampleView.as_view()
 
 
@@ -600,14 +670,13 @@ class AgendaImportEventsView(ManagedAgendaMixin, FormView):
         if form.events:
             for event in form.events:
                 event.agenda_id = self.kwargs['pk']
-                if event.slug and Event.objects.filter(
-                        agenda_id=event.agenda_id,
-                        slug=event.slug).exists():
+                if event.slug and Event.objects.filter(agenda_id=event.agenda_id, slug=event.slug).exists():
                     raise ValidationError(_('Duplicated event identifier'))
                 event.save()
             messages.info(self.request, _('%d events have been imported.') % len(form.events))
         return super(AgendaImportEventsView, self).form_valid(form)
 
+
 agenda_import_events = AgendaImportEventsView.as_view()
 
 
@@ -616,6 +685,7 @@ class EventEditView(ManagedAgendaSubobjectMixin, UpdateView):
     model = Event
     form_class = EventForm
 
+
 event_edit = EventEditView.as_view()
 
 
@@ -626,8 +696,9 @@ class EventDeleteView(ManagedAgendaSubobjectMixin, DeleteView):
     def get_context_data(self, **kwargs):
         context = super(EventDeleteView, self).get_context_data(**kwargs)
         context['cannot_delete'] = bool(
-                self.object.booking_set.filter(cancellation_datetime__isnull=True).exists() and
-                self.object.start_datetime > now())
+            self.object.booking_set.filter(cancellation_datetime__isnull=True).exists()
+            and self.object.start_datetime > now()
+        )
         return context
 
     def delete(self, request, *args, **kwargs):
@@ -637,6 +708,7 @@ class EventDeleteView(ManagedAgendaSubobjectMixin, DeleteView):
             raise PermissionDenied()
         return super(EventDeleteView, self).delete(request, *args, **kwargs)
 
+
 event_delete = EventDeleteView.as_view()
 
 
@@ -645,13 +717,16 @@ class AgendaAddMeetingTypeView(ManagedAgendaMixin, CreateView):
     model = Event
     form_class = NewMeetingTypeForm
 
+
 agenda_add_meeting_type = AgendaAddMeetingTypeView.as_view()
 
+
 class MeetingTypeEditView(ManagedAgendaSubobjectMixin, UpdateView):
     template_name = 'chrono/manager_meeting_type_form.html'
     model = MeetingType
     form_class = MeetingTypeForm
 
+
 meeting_type_edit = MeetingTypeEditView.as_view()
 
 
@@ -659,6 +734,7 @@ class MeetingTypeDeleteView(ManagedAgendaSubobjectMixin, DeleteView):
     template_name = 'chrono/manager_confirm_delete.html'
     model = MeetingType
 
+
 meeting_type_delete = MeetingTypeDeleteView.as_view()
 
 
@@ -669,13 +745,15 @@ class AgendaAddTimePeriodView(ManagedDeskMixin, FormView):
     def form_valid(self, form):
         for weekday in form.cleaned_data.get('weekdays'):
             period = TimePeriod(
-                    weekday=weekday,
-                    start_time=form.cleaned_data['start_time'],
-                    end_time=form.cleaned_data['end_time'],
-                    desk=self.desk)
+                weekday=weekday,
+                start_time=form.cleaned_data['start_time'],
+                end_time=form.cleaned_data['end_time'],
+                desk=self.desk,
+            )
             period.save()
         return super(AgendaAddTimePeriodView, self).form_valid(form)
 
+
 agenda_add_time_period = AgendaAddTimePeriodView.as_view()
 
 
@@ -684,6 +762,7 @@ class TimePeriodEditView(ManagedDeskSubobjectMixin, UpdateView):
     model = TimePeriod
     form_class = TimePeriodForm
 
+
 time_period_edit = TimePeriodEditView.as_view()
 
 
@@ -691,6 +770,7 @@ class TimePeriodDeleteView(ManagedDeskSubobjectMixin, DeleteView):
     template_name = 'chrono/manager_confirm_delete.html'
     model = TimePeriod
 
+
 time_period_delete = TimePeriodDeleteView.as_view()
 
 
@@ -719,9 +799,8 @@ class DeskDeleteView(ManagedAgendaSubobjectMixin, DeleteView):
     def get_context_data(self, **kwargs):
         context = super(DeskDeleteView, self).get_context_data(**kwargs)
         context['cannot_delete'] = Booking.objects.filter(
-                event__desk=self.get_object(),
-                event__start_datetime__gt=now(),
-                cancellation_datetime__isnull=True).exists()
+            event__desk=self.get_object(), event__start_datetime__gt=now(), cancellation_datetime__isnull=True
+        ).exists()
         return context
 
     def delete(self, request, *args, **kwargs):
@@ -812,7 +891,9 @@ class DeskImportTimePeriodExceptionsView(ManagedAgendaSubobjectMixin, UpdateView
                 ics_file_content = force_text(form.cleaned_data['ics_file'].read())
                 exceptions = form.instance.create_timeperiod_exceptions_from_ics(ics_file_content)
             elif form.cleaned_data['ics_url']:
-                exceptions = form.instance.create_timeperiod_exceptions_from_remote_ics(form.cleaned_data['ics_url'])
+                exceptions = form.instance.create_timeperiod_exceptions_from_remote_ics(
+                    form.cleaned_data['ics_url']
+                )
             else:
                 form.instance.remove_timeperiod_exceptions_from_remote_ics()
         except ICSError as e:
@@ -821,21 +902,28 @@ class DeskImportTimePeriodExceptionsView(ManagedAgendaSubobjectMixin, UpdateView
         form.instance.timeperiod_exceptions_remote_url = form.cleaned_data['ics_url']
         form.instance.save()
         if exceptions is not None:
-            message = ungettext('An exception has been imported.',
-                                '%(count)d exceptions have been imported.', exceptions)
+            message = ungettext(
+                'An exception has been imported.', '%(count)d exceptions have been imported.', exceptions
+            )
             message = message % {'count': exceptions}
             messages.info(self.request, message)
         return super(DeskImportTimePeriodExceptionsView, self).form_valid(form)
 
+
 desk_import_time_period_exceptions = DeskImportTimePeriodExceptionsView.as_view()
 
 
 def menu_json(request):
     label = _('Agendas')
-    json_str = json.dumps([{'label': force_text(label),
-        'slug': 'calendar',
-        'url': request.build_absolute_uri(reverse('chrono-manager-homepage'))
-        }])
+    json_str = json.dumps(
+        [
+            {
+                'label': force_text(label),
+                'slug': 'calendar',
+                'url': request.build_absolute_uri(reverse('chrono-manager-homepage')),
+            }
+        ]
+    )
     content_type = 'application/json'
     for variable in ('jsonpCallback', 'callback'):
         if variable in request.GET:
diff --git a/chrono/manager/widgets.py b/chrono/manager/widgets.py
index f3387c0..c572f42 100644
--- a/chrono/manager/widgets.py
+++ b/chrono/manager/widgets.py
@@ -11,7 +11,7 @@ import json
 import re
 import uuid
 
-from django.forms.widgets import DateTimeInput, TimeInput, SelectMultiple
+from django.forms.widgets import DateTimeInput, SelectMultiple, TimeInput
 from django.utils.formats import get_language
 from django.utils.safestring import mark_safe
 
@@ -39,7 +39,7 @@ DATE_FORMAT_PY_JS_MAPPING = {
     '%Y': 'yyyy',
     '%y': 'yy',
     '%p': 'P',
-    '%S': 'ss'
+    '%S': 'ss',
 }
 
 DATE_FORMAT_TO_JS_REGEX = re.compile(r'(?<!\w)(' + '|'.join(DATE_FORMAT_PY_JS_MAPPING.keys()) + r')\b')
@@ -77,9 +77,8 @@ class PickerWidgetMixin(object):
         # with a default, and convert it to a Python data format for later string parsing
         date_format = self.options['format']
         self.format = DATE_FORMAT_TO_PYTHON_REGEX.sub(
-            lambda x: DATE_FORMAT_JS_PY_MAPPING[x.group()],
-            date_format
-            )
+            lambda x: DATE_FORMAT_JS_PY_MAPPING[x.group()], date_format
+        )
 
         super(PickerWidgetMixin, self).__init__(attrs, format=self.format)
 
@@ -87,7 +86,7 @@ class PickerWidgetMixin(object):
         final_attrs = self.build_attrs(attrs)
         rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs, renderer=renderer)
 
-        #if not set, autoclose have to be true.
+        # if not set, autoclose have to be true.
         self.options.setdefault('autoclose', True)
 
         # Build javascript options out of python dictionary
@@ -100,13 +99,15 @@ class PickerWidgetMixin(object):
         # Use provided id or generate hex to avoid collisions in document
         id = final_attrs.get('id', uuid.uuid4().hex)
 
-        return mark_safe(BOOTSTRAP_INPUT_TEMPLATE % dict(
-                    id=id,
-                    rendered_widget=rendered_widget,
-                    clear_button=CLEAR_BTN_TEMPLATE if self.options.get('clearBtn') else '',
-                    glyphicon=self.glyphicon,
-                    options=js_options
-                    )
+        return mark_safe(
+            BOOTSTRAP_INPUT_TEMPLATE
+            % dict(
+                id=id,
+                rendered_widget=rendered_widget,
+                clear_button=CLEAR_BTN_TEMPLATE if self.options.get('clearBtn') else '',
+                glyphicon=self.glyphicon,
+                options=js_options,
+            )
         )
 
 
@@ -136,6 +137,7 @@ class TimeWidget(TimeInput):
     input type and has a bit of a fallback mechanism with the presence
     of the pattern attribute in case a standard text input is used.
     """
+
     input_type = 'time'
 
     def __init__(self, **kwargs):
@@ -149,13 +151,17 @@ class WeekdaysWidget(SelectMultiple):
         s = []
         value = value or []
         for choice_id, choice_label in self.choices:
-            s.append('<li><label><input type="checkbox" '
-                     '  name="%(name)s-%(choice_id)s" %(checked)s>'
-                     '<span>%(choice_label)s</span></label></li>' % {
-                         'name': name,
-                         'checked': 'checked' if choice_id in value else '',
-                         'choice_id': choice_id,
-                         'choice_label': choice_label})
+            s.append(
+                '<li><label><input type="checkbox" '
+                '  name="%(name)s-%(choice_id)s" %(checked)s>'
+                '<span>%(choice_label)s</span></label></li>'
+                % {
+                    'name': name,
+                    'checked': 'checked' if choice_id in value else '',
+                    'choice_id': choice_id,
+                    'choice_label': choice_label,
+                }
+            )
         return mark_safe('<ul id="%(id)s">' % attrs + '\n'.join(s) + '</ul>')
 
     def value_from_datadict(self, data, files, name):
diff --git a/chrono/settings.py b/chrono/settings.py
index b5163b3..f1135d2 100644
--- a/chrono/settings.py
+++ b/chrono/settings.py
@@ -24,6 +24,7 @@ and to disable DEBUG mode in production.
 """
 
 import os
+
 from django.conf.global_settings import STATICFILES_FINDERS
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
@@ -77,10 +78,7 @@ WSGI_APPLICATION = 'chrono.wsgi.application'
 # https://docs.djangoproject.com/en/1.7/ref/settings/#databases
 
 DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
-    }
+    'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),}
 }
 
 # Internationalization
@@ -96,7 +94,7 @@ USE_L10N = True
 
 USE_TZ = True
 
-LOCALE_PATHS = (os.path.join(BASE_DIR, 'chrono', 'locale'), )
+LOCALE_PATHS = (os.path.join(BASE_DIR, 'chrono', 'locale'),)
 
 FORMAT_MODULE_PATH = 'chrono.formats'
 
@@ -104,8 +102,7 @@ FORMAT_MODULE_PATH = 'chrono.formats'
 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [
-        ],
+        'DIRS': [],
         'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
@@ -165,7 +162,8 @@ MELLON_IDENTITY_PROVIDERS = []
 # (see http://docs.python-requests.org/en/master/user/advanced/#proxies)
 REQUESTS_PROXIES = None
 
-local_settings_file = os.environ.get('CHRONO_SETTINGS_FILE',
-        os.path.join(os.path.dirname(__file__), 'local_settings.py'))
+local_settings_file = os.environ.get(
+    'CHRONO_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')
+)
 if os.path.exists(local_settings_file):
     exec(open(local_settings_file).read())
diff --git a/chrono/urls.py b/chrono/urls.py
index 9f44117..b97d165 100644
--- a/chrono/urls.py
+++ b/chrono/urls.py
@@ -19,17 +19,14 @@ from django.conf.urls import include, url
 from django.conf.urls.static import static
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
-from .urls_utils import decorated_includes, manager_required
-
-from .views import homepage, LoginView, LogoutView
 from .api.urls import urlpatterns as chrono_api_urls
 from .manager.urls import urlpatterns as chrono_manager_urls
-
+from .urls_utils import decorated_includes, manager_required
+from .views import LoginView, LogoutView, homepage
 
 urlpatterns = [
     url(r'^$', homepage, name='home'),
-    url(r'^manage/', decorated_includes(manager_required,
-        include(chrono_manager_urls))),
+    url(r'^manage/', decorated_includes(manager_required, include(chrono_manager_urls))),
     url(r'^api/', include(chrono_api_urls)),
     url(r'^logout/$', LogoutView.as_view(), name='auth_logout'),
     url(r'^login/$', LoginView.as_view(), name='auth_login'),
diff --git a/chrono/urls_utils.py b/chrono/urls_utils.py
index b4f38b2..2109b1b 100644
--- a/chrono/urls_utils.py
+++ b/chrono/urls_utils.py
@@ -17,7 +17,6 @@
 # Decorating URL includes, <https://djangosnippets.org/snippets/2532/>
 
 import django
-
 from django.contrib.auth.decorators import user_passes_test
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
@@ -37,6 +36,7 @@ class DecoratedURLPattern(URLPattern):
             result.func = self._decorate_with(result.func)
         return result
 
+
 def decorated_includes(func, includes, *args, **kwargs):
     urlconf_module, app_name, namespace = includes
 
@@ -59,6 +59,7 @@ def manager_required(function=None, login_url=None):
             raise PermissionDenied()
         # As the last resort, show the login form
         return False
+
     actual_decorator = user_passes_test(check_manager, login_url=login_url)
     if function:
         return actual_decorator(function)
diff --git a/chrono/views.py b/chrono/views.py
index 56333b5..2ce6833 100644
--- a/chrono/views.py
+++ b/chrono/views.py
@@ -23,7 +23,6 @@ from django.shortcuts import resolve_url
 from django.utils.decorators import method_decorator
 from django.views.decorators.cache import never_cache
 
-
 if 'mellon' in settings.INSTALLED_APPS:
     from mellon.utils import get_idps
 else:
@@ -35,8 +34,9 @@ class LoginView(auth_views.LoginView):
         if any(get_idps()):
             if not 'next' in request.GET:
                 return HttpResponseRedirect(resolve_url('mellon_login'))
-            return HttpResponseRedirect(resolve_url('mellon_login') + '?next='
-                                        + quote(request.GET.get('next')))
+            return HttpResponseRedirect(
+                resolve_url('mellon_login') + '?next=' + quote(request.GET.get('next'))
+            )
         return super(LoginView, self).get(request, *args, **kwargs)
 
 
diff --git a/chrono/wsgi.py b/chrono/wsgi.py
index e7d8e42..8e06067 100644
--- a/chrono/wsgi.py
+++ b/chrono/wsgi.py
@@ -8,7 +8,10 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
 """
 
 import os
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chrono.settings")
 
 from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chrono.settings")
+
+
 application = get_wsgi_application()
diff --git a/tests/conftest.py b/tests/conftest.py
index 5eebfd4..2a30bb4 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,8 +1,7 @@
+import django_webtest
 import pytest
-
 from django.contrib.auth.models import User
 
-import django_webtest
 
 @pytest.fixture
 def app(request):
diff --git a/tests/test_agendas.py b/tests/test_agendas.py
index 820d8a2..115bc52 100644
--- a/tests/test_agendas.py
+++ b/tests/test_agendas.py
@@ -1,17 +1,14 @@
-import pytest
 import datetime
-import mock
 import re
-import requests
-
 
-from django.utils.timezone import now, make_aware, localtime
+import mock
+import pytest
+import requests
 from django.contrib.auth.models import Group
 from django.core.management import call_command
-from django.core.management.base import CommandError
+from django.utils.timezone import localtime, make_aware, now
 
-from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
-                        Desk, TimePeriod, TimePeriodException, ICSError)
+from chrono.agendas.models import Agenda, Booking, Desk, Event, ICSError, MeetingType, TimePeriodException
 
 pytestmark = pytest.mark.django_db
 
@@ -154,6 +151,7 @@ def test_event_manager():
     booking.save()
     assert Event.objects.all()[0].booked_places == 0
 
+
 def test_event_bookable_period():
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
@@ -179,6 +177,7 @@ def test_event_bookable_period():
     event.save()
     assert event.in_bookable_period() is False
 
+
 def test_meeting_type_slugs():
     agenda1 = Agenda(label=u'Foo bar')
     agenda1.save()
@@ -197,6 +196,7 @@ def test_meeting_type_slugs():
     meeting_type3.save()
     assert meeting_type3.slug == 'baz'
 
+
 def test_timeperiodexception_creation_from_ics():
     agenda = Agenda(label=u'Test 1 agenda')
     agenda.save()
@@ -206,6 +206,7 @@ def test_timeperiodexception_creation_from_ics():
     assert exceptions_count == 2
     assert TimePeriodException.objects.filter(desk=desk).count() == 2
 
+
 def test_timeperiodexception_creation_from_ics_without_startdt():
     agenda = Agenda(label=u'Test 2 agenda')
     agenda.save()
@@ -222,6 +223,7 @@ def test_timeperiodexception_creation_from_ics_without_startdt():
         exceptions_count = desk.create_timeperiod_exceptions_from_ics(ics_sample)
     assert 'Event "Event 1" has no start date.' == str(e.value)
 
+
 def test_timeperiodexception_creation_from_ics_without_enddt():
     agenda = Agenda(label=u'Test 3 agenda')
     agenda.save()
@@ -248,14 +250,17 @@ def test_timeperiodexception_creation_from_ics_with_recurrences():
     desk.save()
     assert desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_RECURRENT_EVENT) == 3
     assert TimePeriodException.objects.filter(desk=desk).count() == 3
-    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set([
-        make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2019, 1, 1))])
+    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set(
+        [make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2019, 1, 1))]
+    )
     assert desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_RECURRENT_EVENT) == 0
     # verify occurences are cleaned when count changed
     assert desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_RECURRENT_EVENT_2) == 0
     assert TimePeriodException.objects.filter(desk=desk).count() == 2
-    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set([
-        make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2018, 1, 2))])
+    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set(
+        [make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2018, 1, 2))]
+    )
+
 
 def test_timeexception_creation_from_ics_with_dates():
     agenda = Agenda(label=u'Test 5 agenda')
@@ -275,6 +280,7 @@ def test_timeexception_creation_from_ics_with_dates():
         assert localtime(exception.start_datetime) == make_aware(datetime.datetime(2018, 1, 1, 0, 0))
         assert localtime(exception.end_datetime) == make_aware(datetime.datetime(2018, 1, 1, 0, 0))
 
+
 def test_timeexception_create_from_invalid_ics():
     agenda = Agenda(label=u'Test 6 agenda')
     agenda.save()
@@ -284,6 +290,7 @@ def test_timeexception_create_from_invalid_ics():
         exceptions_count = desk.create_timeperiod_exceptions_from_ics(INVALID_ICS_SAMPLE)
     assert str(e.value) == 'File format is invalid.'
 
+
 def test_timeexception_create_from_ics_with_no_events():
     agenda = Agenda(label=u'Test 7 agenda')
     agenda.save()
@@ -293,6 +300,7 @@ def test_timeexception_create_from_ics_with_no_events():
         exceptions_count = desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_NO_EVENTS)
     assert str(e.value) == "The file doesn't contain any events."
 
+
 @mock.patch('chrono.agendas.models.requests.get')
 def test_timeperiodexception_creation_from_remote_ics(mocked_get):
     agenda = Agenda(label=u'Test 8 agenda')
@@ -316,6 +324,7 @@ def test_timeperiodexception_creation_from_remote_ics(mocked_get):
     assert exceptions_count == 0
     TimePeriodException.objects.filter(external_id='desk-%s:' % desk.id).count() == 0
 
+
 @mock.patch('chrono.agendas.models.requests.get')
 def test_timeperiodexception_creation_from_unreachable_remote_ics(mocked_get):
     agenda = Agenda(label=u'Test 9 agenda')
@@ -325,13 +334,16 @@ def test_timeperiodexception_creation_from_unreachable_remote_ics(mocked_get):
     mocked_response = mock.Mock()
     mocked_response.text = ICS_SAMPLE
     mocked_get.return_value = mocked_response
+
     def mocked_requests_connection_error(*args, **kwargs):
         raise requests.ConnectionError('unreachable')
+
     mocked_get.side_effect = mocked_requests_connection_error
     with pytest.raises(ICSError) as e:
         exceptions_count = desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
     assert str(e.value) == "Failed to retrieve remote calendar (http://example.com/sample.ics, unreachable)."
 
+
 @mock.patch('chrono.agendas.models.requests.get')
 def test_timeperiodexception_creation_from_forbidden_remote_ics(mocked_get):
     agenda = Agenda(label=u'Test 10 agenda')
@@ -341,35 +353,50 @@ def test_timeperiodexception_creation_from_forbidden_remote_ics(mocked_get):
     mocked_response = mock.Mock()
     mocked_response.status_code = 403
     mocked_get.return_value = mocked_response
+
     def mocked_requests_http_forbidden_error(*args, **kwargs):
         raise requests.HTTPError(response=mocked_response)
+
     mocked_get.side_effect = mocked_requests_http_forbidden_error
 
     with pytest.raises(ICSError) as e:
         exceptions_count = desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
-    assert str(e.value) == "Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403)."
+    assert (
+        str(e.value) == "Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403)."
+    )
+
 
 @mock.patch('chrono.agendas.models.requests.get')
 def test_sync_desks_timeperiod_exceptions_from_ics(mocked_get, capsys):
     agenda = Agenda(label=u'Test 11 agenda')
     agenda.save()
-    desk = Desk(label='Test 11 desk', agenda=agenda, timeperiod_exceptions_remote_url='http://example.com/sample.ics')
+    desk = Desk(
+        label='Test 11 desk', agenda=agenda, timeperiod_exceptions_remote_url='http://example.com/sample.ics'
+    )
     desk.save()
     mocked_response = mock.Mock()
     mocked_response.status_code = 403
     mocked_get.return_value = mocked_response
+
     def mocked_requests_http_forbidden_error(*args, **kwargs):
         raise requests.HTTPError(response=mocked_response)
+
     mocked_get.side_effect = mocked_requests_http_forbidden_error
     call_command('sync_desks_timeperiod_exceptions')
     out, err = capsys.readouterr()
-    assert err == 'unable to create timeperiod exceptions for "Test 11 desk": Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403).\n'
+    assert (
+        err
+        == 'unable to create timeperiod exceptions for "Test 11 desk": Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403).\n'
+    )
+
 
 @mock.patch('chrono.agendas.models.requests.get')
 def test_sync_desks_timeperiod_exceptions_from_changing_ics(mocked_get, caplog):
     agenda = Agenda(label=u'Test 11 agenda')
     agenda.save()
-    desk = Desk(label='Test 11 desk', agenda=agenda, timeperiod_exceptions_remote_url='http:example.com/sample.ics')
+    desk = Desk(
+        label='Test 11 desk', agenda=agenda, timeperiod_exceptions_remote_url='http:example.com/sample.ics'
+    )
     desk.save()
     mocked_response = mock.Mock()
     mocked_response.text = ICS_SAMPLE
@@ -397,6 +424,7 @@ END:VCALENDAR"""
     call_command('sync_desks_timeperiod_exceptions')
     assert not TimePeriodException.objects.filter(desk=desk).exists()
 
+
 def test_base_meeting_duration():
     agenda = Agenda(label='Meeting', kind='meetings')
     agenda.save()
@@ -427,14 +455,18 @@ def test_timeperiodexception_creation_from_ics_with_duration():
     exceptions_count = desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_DURATION)
     assert exceptions_count == 2
     assert TimePeriodException.objects.filter(desk=desk).count() == 2
-    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set([
-        make_aware(datetime.datetime(2017, 8, 31, 19, 8, 0)),
-        make_aware(datetime.datetime(2017, 8, 30, 20, 8, 0)),
-    ])
-    assert set(TimePeriodException.objects.values_list('end_datetime', flat=True)) == set([
-        make_aware(datetime.datetime(2017, 8, 31, 22, 34, 0)),
-        make_aware(datetime.datetime(2017, 9, 1, 0, 34, 0)),
-    ])
+    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set(
+        [
+            make_aware(datetime.datetime(2017, 8, 31, 19, 8, 0)),
+            make_aware(datetime.datetime(2017, 8, 30, 20, 8, 0)),
+        ]
+    )
+    assert set(TimePeriodException.objects.values_list('end_datetime', flat=True)) == set(
+        [
+            make_aware(datetime.datetime(2017, 8, 31, 22, 34, 0)),
+            make_aware(datetime.datetime(2017, 9, 1, 0, 34, 0)),
+        ]
+    )
 
 
 @pytest.mark.freeze_time('2017-12-01')
@@ -447,8 +479,9 @@ def test_timeperiodexception_creation_from_ics_with_recurrences_in_the_past():
     desk.save()
     assert desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_RECURRENT_EVENT_IN_THE_PAST) == 2
     assert TimePeriodException.objects.filter(desk=desk).count() == 2
-    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set([
-        make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2019, 1, 1))])
+    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set(
+        [make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2019, 1, 1))]
+    )
     assert desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_RECURRENT_EVENT_IN_THE_PAST) == 0
 
 
diff --git a/tests/test_api.py b/tests/test_api.py
index ce5d1ab..b7ab267 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1,19 +1,16 @@
 import datetime
-import urllib.parse as urlparse
-import pytest
 import sys
+import urllib.parse as urlparse
 
+import pytest
 from django.contrib.auth import get_user_model
 from django.db import connection
 from django.test import override_settings
 from django.test.utils import CaptureQueriesContext
-from django.utils.timezone import now, make_aware, localtime
+from django.utils.timezone import localtime, make_aware, now
 
-from chrono.agendas.models import (Agenda, Event, Booking,
-                                   MeetingType, TimePeriod, Desk,
-                                   TimePeriodException)
 import chrono.api.views
-
+from chrono.agendas.models import Agenda, Booking, Desk, Event, MeetingType, TimePeriod, TimePeriodException
 
 pytestmark = pytest.mark.django_db
 
@@ -25,29 +22,36 @@ def datetime_from_str(dt_str):
 @pytest.fixture
 def user():
     User = get_user_model()
-    user = User.objects.create(username='john.doe',
-            first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
+    user = User.objects.create(
+        username='john.doe', first_name=u'John', last_name=u'Doe', email='john.doe@example.net'
+    )
     user.set_password('password')
     user.save()
     return user
 
+
 @pytest.fixture(params=['Europe/Brussels', 'Asia/Kolkata', 'Brazil/East'])
 def time_zone(request, settings):
     settings.TIME_ZONE = request.param
 
 
-@pytest.fixture(params=[
-    datetime.datetime(2017, 5, 20, 1, 12),
-    datetime.datetime(2017, 5, 20, 11, 42),
-    datetime.datetime(2017, 5, 20, 23, 17)])
+@pytest.fixture(
+    params=[
+        datetime.datetime(2017, 5, 20, 1, 12),
+        datetime.datetime(2017, 5, 20, 11, 42),
+        datetime.datetime(2017, 5, 20, 23, 17),
+    ]
+)
 def mock_now(request, monkeypatch):
     def mockreturn():
         return make_aware(request.param)
+
     monkeypatch.setattr(chrono.api.views, 'now', mockreturn)
     monkeypatch.setattr(chrono.agendas.models, 'now', mockreturn)
     monkeypatch.setattr(sys.modules[__name__], 'now', mockreturn)
     return mockreturn()
 
+
 @pytest.fixture
 def some_data(time_zone, mock_now):
     agenda = Agenda(label=u'Foo bar')
@@ -55,8 +59,7 @@ def some_data(time_zone, mock_now):
     first_date = localtime(now()).replace(hour=17, minute=0, second=0, microsecond=0)
     first_date += datetime.timedelta(days=1)
     for i in range(3):
-        event = Event(start_datetime=first_date + datetime.timedelta(days=i),
-                  places=20, agenda=agenda)
+        event = Event(start_datetime=first_date + datetime.timedelta(days=i), places=20, agenda=agenda)
         event.save()
 
     agenda2 = Agenda(label=u'Foo bar2')
@@ -64,19 +67,19 @@ def some_data(time_zone, mock_now):
     first_date = localtime(now()).replace(hour=20, minute=0, second=0, microsecond=0)
     first_date += datetime.timedelta(days=1)
     for i in range(2):
-        event = Event(start_datetime=first_date + datetime.timedelta(days=i),
-                  places=20, agenda=agenda2)
+        event = Event(start_datetime=first_date + datetime.timedelta(days=i), places=20, agenda=agenda2)
         event.save()
 
     # a date in the past
-    event = Event(start_datetime=first_date - datetime.timedelta(days=10),
-            places=10, agenda=agenda)
+    event = Event(start_datetime=first_date - datetime.timedelta(days=10), places=10, agenda=agenda)
     event.save()
 
+
 @pytest.fixture
 def meetings_agenda(time_zone, mock_now):
-    agenda = Agenda(label=u'Foo bar Meeting', kind='meetings',
-            minimal_booking_delay=1, maximal_booking_delay=56)
+    agenda = Agenda(
+        label=u'Foo bar Meeting', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=56
+    )
     agenda.save()
     meeting_type = MeetingType(agenda=agenda, label='Blah', duration=30)
     meeting_type.save()
@@ -86,48 +89,84 @@ def meetings_agenda(time_zone, mock_now):
 
     default_desk, created = Desk.objects.get_or_create(agenda=agenda, label='Desk 1')
 
-    time_period = TimePeriod(weekday=test_1st_weekday,
-            start_time=datetime.time(10, 0), end_time=datetime.time(12, 0), desk=default_desk)
+    time_period = TimePeriod(
+        weekday=test_1st_weekday,
+        start_time=datetime.time(10, 0),
+        end_time=datetime.time(12, 0),
+        desk=default_desk,
+    )
     time_period.save()
-    time_period = TimePeriod(weekday=test_2nd_weekday,
-            start_time=datetime.time(10, 0), end_time=datetime.time(17, 0), desk=default_desk)
+    time_period = TimePeriod(
+        weekday=test_2nd_weekday,
+        start_time=datetime.time(10, 0),
+        end_time=datetime.time(17, 0),
+        desk=default_desk,
+    )
     time_period.save()
     return agenda
 
+
 def test_agendas_api(app, some_data, meetings_agenda):
     agenda1 = Agenda.objects.filter(label=u'Foo bar')[0]
     agenda2 = Agenda.objects.filter(label=u'Foo bar2')[0]
     resp = app.get('/api/agenda/')
-    assert resp.json == {'data': [
-        {'text': 'Foo bar', 'id': u'foo-bar', 'slug': 'foo-bar', 'kind': 'events',
-         'minimal_booking_delay': 1, 'maximal_booking_delay': 56,
-         'api': {'datetimes_url': 'http://testserver/api/agenda/%s/datetimes/' % agenda1.slug,
-                 'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % agenda1.slug}},
-        {'text': 'Foo bar Meeting', 'id': u'foo-bar-meeting', 'slug': 'foo-bar-meeting',
-         'minimal_booking_delay': 1, 'maximal_booking_delay': 56,
-         'kind': 'meetings',
-         'api': {'meetings_url': 'http://testserver/api/agenda/%s/meetings/' % meetings_agenda.slug,
-                 'desks_url': 'http://testserver/api/agenda/%s/desks/' % meetings_agenda.slug,
-                 'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % meetings_agenda.slug,
+    assert resp.json == {
+        'data': [
+            {
+                'text': 'Foo bar',
+                'id': u'foo-bar',
+                'slug': 'foo-bar',
+                'kind': 'events',
+                'minimal_booking_delay': 1,
+                'maximal_booking_delay': 56,
+                'api': {
+                    'datetimes_url': 'http://testserver/api/agenda/%s/datetimes/' % agenda1.slug,
+                    'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % agenda1.slug,
                 },
-        },
-        {'text': 'Foo bar2', 'id': u'foo-bar2', 'kind': 'events', 'slug': 'foo-bar2',
-         'minimal_booking_delay': 1, 'maximal_booking_delay': 56,
-         'api': {'datetimes_url': 'http://testserver/api/agenda/%s/datetimes/' % agenda2.slug,
-                 'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % agenda2.slug}}
-        ]}
+            },
+            {
+                'text': 'Foo bar Meeting',
+                'id': u'foo-bar-meeting',
+                'slug': 'foo-bar-meeting',
+                'minimal_booking_delay': 1,
+                'maximal_booking_delay': 56,
+                'kind': 'meetings',
+                'api': {
+                    'meetings_url': 'http://testserver/api/agenda/%s/meetings/' % meetings_agenda.slug,
+                    'desks_url': 'http://testserver/api/agenda/%s/desks/' % meetings_agenda.slug,
+                    'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % meetings_agenda.slug,
+                },
+            },
+            {
+                'text': 'Foo bar2',
+                'id': u'foo-bar2',
+                'kind': 'events',
+                'slug': 'foo-bar2',
+                'minimal_booking_delay': 1,
+                'maximal_booking_delay': 56,
+                'api': {
+                    'datetimes_url': 'http://testserver/api/agenda/%s/datetimes/' % agenda2.slug,
+                    'fillslots_url': 'http://testserver/api/agenda/%s/fillslots/' % agenda2.slug,
+                },
+            },
+        ]
+    }
+
 
 def test_agendas_meetingtypes_api(app, some_data, meetings_agenda):
     resp = app.get('/api/agenda/%s/meetings/' % meetings_agenda.slug)
-    assert resp.json == {'data': [
-        {'text': 'Blah',
-         'id': 'blah',
-         'duration': 30,
-         'api': {
-             'datetimes_url': 'http://testserver/api/agenda/foo-bar-meeting/meetings/blah/datetimes/',
-         }
-        }
-    ]}
+    assert resp.json == {
+        'data': [
+            {
+                'text': 'Blah',
+                'id': 'blah',
+                'duration': 30,
+                'api': {
+                    'datetimes_url': 'http://testserver/api/agenda/foo-bar-meeting/meetings/blah/datetimes/',
+                },
+            }
+        ]
+    }
 
     # wrong kind
     agenda1 = Agenda.objects.filter(label=u'Foo bar')[0]
@@ -139,11 +178,7 @@ def test_agendas_meetingtypes_api(app, some_data, meetings_agenda):
 
 def test_agendas_desks_api(app, some_data, meetings_agenda):
     resp = app.get('/api/agenda/%s/desks/' % meetings_agenda.slug)
-    assert resp.json == {'data': [
-        {'text': 'Desk 1',
-         'id': 'desk-1',
-        }
-    ]}
+    assert resp.json == {'data': [{'text': 'Desk 1', 'id': 'desk-1',}]}
 
     # wrong kind
     agenda1 = Agenda.objects.filter(label=u'Foo bar')[0]
@@ -198,12 +233,14 @@ def test_datetimes_api(app, some_data):
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
     assert resp.json['data'][0]['description']
 
+
 def test_datetimes_api_wrong_kind(app, some_data):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     agenda.kind = 'meetings'
     agenda.save()
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.id, status=404)
 
+
 def test_datetime_api_fr(app, some_data):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     with override_settings(LANGUAGE_CODE='fr-fr'):
@@ -213,6 +250,7 @@ def test_datetime_api_fr(app, some_data):
         assert resp.json['data'][0]['datetime'].endswith(' 17:00:00')
         assert 'data' in resp.json
 
+
 def test_datetime_api_label(app, some_data):
     agenda_id = Agenda.objects.filter(label=u'Foo bar2')[0].id
     event = Event.objects.filter(agenda=agenda_id)[0]
@@ -221,17 +259,20 @@ def test_datetime_api_label(app, some_data):
     resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
     assert 'Hello world' in [x['text'] for x in resp.json['data']]
 
+
 def test_datetime_api_status_url(app, some_data):
     agenda = Agenda.objects.get(label=u'Foo bar2')
     resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
     for datum in resp.json['data']:
         assert urlparse.urlparse(datum['api']['status_url']).path == '/api/agenda/%s/status/%s/' % (
-                agenda.slug, datum['slug'] or datum['id'])
+            agenda.slug,
+            datum['slug'] or datum['id'],
+        )
+
 
 def test_datetimes_api_meetings_agenda(app, meetings_agenda):
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
-    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (
-            meeting_type.agenda.slug, meeting_type.slug)
+    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (meeting_type.agenda.slug, meeting_type.slug)
 
     resp = app.get('/api/agenda/%s/meetings/xxx/datetimes/' % meeting_type.agenda.slug, status=404)
 
@@ -253,8 +294,14 @@ def test_datetimes_api_meetings_agenda(app, meetings_agenda):
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     dt = datetime.datetime.strptime(resp.json['data'][2]['id'].split(':')[1], '%Y-%m-%d-%H%M')
-    ev = Event(agenda=meetings_agenda, meeting_type=meeting_type,
-            places=1, full=False, start_datetime=make_aware(dt), desk=Desk.objects.first())
+    ev = Event(
+        agenda=meetings_agenda,
+        meeting_type=meeting_type,
+        places=1,
+        full=False,
+        start_datetime=make_aware(dt),
+        desk=Desk.objects.first(),
+    )
     ev.save()
     booking = Booking(event=ev)
     booking.save()
@@ -277,9 +324,12 @@ def test_datetimes_api_meetings_agenda(app, meetings_agenda):
     default_desk, _ = Desk.objects.get_or_create(agenda=meetings_agenda, slug='desk-1')
     TimePeriod.objects.filter(desk=default_desk).delete()
     start_time = localtime(now()) - datetime.timedelta(minutes=10)
-    time_period = TimePeriod(weekday=localtime(now()).weekday(),
-            start_time=start_time,
-            end_time=start_time + datetime.timedelta(hours=1), desk=default_desk)
+    time_period = TimePeriod(
+        weekday=localtime(now()).weekday(),
+        start_time=start_time,
+        end_time=start_time + datetime.timedelta(hours=1),
+        desk=default_desk,
+    )
     time_period.save()
     meetings_agenda.minimal_booking_delay = 0
     meetings_agenda.maximal_booking_delay = 10
@@ -287,6 +337,7 @@ def test_datetimes_api_meetings_agenda(app, meetings_agenda):
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == 3
 
+
 def test_datetimes_api_meetings_agenda_short_time_periods(app, meetings_agenda, user):
     meetings_agenda.minimal_booking_delay = 0
     meetings_agenda.maximal_booking_delay = 10
@@ -294,14 +345,17 @@ def test_datetimes_api_meetings_agenda_short_time_periods(app, meetings_agenda,
 
     default_desk, _ = Desk.objects.get_or_create(agenda=meetings_agenda, slug='desk-1')
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
-    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (
-            meeting_type.agenda.slug, meeting_type.slug)
+    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (meeting_type.agenda.slug, meeting_type.slug)
 
     # test with short time periods
     TimePeriod.objects.filter(desk=default_desk).delete()
     test_1st_weekday = (localtime(now()).weekday() + 2) % 7
-    time_period = TimePeriod(weekday=test_1st_weekday,
-            start_time=datetime.time(10, 0), end_time=datetime.time(10, 30), desk=default_desk)
+    time_period = TimePeriod(
+        weekday=test_1st_weekday,
+        start_time=datetime.time(10, 0),
+        end_time=datetime.time(10, 30),
+        desk=default_desk,
+    )
     time_period.save()
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == 2
@@ -328,6 +382,7 @@ def test_datetimes_api_meetings_agenda_short_time_periods(app, meetings_agenda,
     assert resp.json['err_class'] == 'no more desk available'
     assert resp.json['err_desc'] == 'no more desk available'
 
+
 def test_booking_api(app, some_data, user):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
@@ -337,8 +392,13 @@ def test_booking_api(app, some_data, user):
 
     for agenda_key in (agenda.slug, agenda.id):  # acces datetimes via agenda slug or id (legacy)
         resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda_key)
-        event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api']['fillslot_url']
-        assert urlparse.urlparse(event_fillslot_url).path == '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug or event.id)
+        event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api'][
+            'fillslot_url'
+        ]
+        assert urlparse.urlparse(event_fillslot_url).path == '/api/agenda/%s/fillslot/%s/' % (
+            agenda.slug,
+            event.slug or event.id,
+        )
 
     app.authorization = ('Basic', ('john.doe', 'password'))
     resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id))
@@ -359,30 +419,39 @@ def test_booking_api(app, some_data, user):
     assert Booking.objects.filter(event__agenda=agenda).count() == 2
 
     # test with additional data
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/'},
+    )
     assert Booking.objects.get(id=resp.json['booking_id']).label == 'foo'
     assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'bar'
     assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == 'http://example.net/'
 
     # blank data are OK
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': '', 'user_name': '', 'backoffice_url': ''})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={'label': '', 'user_name': '', 'backoffice_url': ''},
+    )
     assert Booking.objects.get(id=resp.json['booking_id']).label == ''
     assert Booking.objects.get(id=resp.json['booking_id']).user_name == ''
     assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == ''
 
     # extra data stored in extra_data field
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
+    )
     assert Booking.objects.get(id=resp.json['booking_id']).label == 'l'
     assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'u'
     assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == ''
     assert Booking.objects.get(id=resp.json['booking_id']).extra_data == {'foo': 'bar'}
 
     # test invalid data are refused
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'user_name': {'foo': 'bar'}}, status=400)
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={'user_name': {'foo': 'bar'}},
+        status=400,
+    )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'invalid payload'  # legacy
     assert resp.json['err_class'] == 'invalid payload'
@@ -394,6 +463,7 @@ def test_booking_api(app, some_data, user):
 
     resp = app.post('/api/agenda/233/fillslot/%s/' % event.id, status=404)
 
+
 def test_booking_ics(app, some_data, meetings_agenda, user):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
@@ -407,15 +477,24 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
 
     formatted_start_date = event.start_datetime.strftime('%Y%m%dT%H%M%S')
     booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
-    assert 'UID:%s-%s-%s\r\n' % (event.start_datetime.isoformat(), agenda.pk, resp.json['booking_id']) in booking_ics
+    assert (
+        'UID:%s-%s-%s\r\n' % (event.start_datetime.isoformat(), agenda.pk, resp.json['booking_id'])
+        in booking_ics
+    )
     assert 'SUMMARY:\r\n' in booking_ics
     assert 'DTSTART:%sZ\r\n' % formatted_start_date in booking_ics
     assert 'DTEDND:' not in booking_ics
 
     # test with additional data
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/',
-                    'url': 'http://example.com/booking'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={
+            'label': 'foo',
+            'user_name': 'bar',
+            'backoffice_url': 'http://example.net/',
+            'url': 'http://example.com/booking',
+        },
+    )
     assert Booking.objects.count() == 2
     booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
     assert 'SUMMARY:foo\r\n' in booking_ics
@@ -423,9 +502,16 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
     assert 'URL:http://example.com/booking\r\n' in booking_ics
 
     # test with user_label in additionnal data
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/',
-                    'url': 'http://example.com/booking', 'user_display_label': 'your booking'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={
+            'label': 'foo',
+            'user_name': 'bar',
+            'backoffice_url': 'http://example.net/',
+            'url': 'http://example.com/booking',
+            'user_display_label': 'your booking',
+        },
+    )
     assert Booking.objects.count() == 3
     booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
     assert 'SUMMARY:your booking\r\n' in booking_ics
@@ -433,9 +519,17 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
     assert 'URL:http://example.com/booking\r\n' in booking_ics
 
     # extra data stored in extra_data field
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
-            params={'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'location': 'bar',
-                    'comment': 'booking comment', 'description': 'booking description'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
+        params={
+            'label': 'l',
+            'user_name': 'u',
+            'backoffice_url': '',
+            'location': 'bar',
+            'comment': 'booking comment',
+            'description': 'booking description',
+        },
+    )
     assert Booking.objects.count() == 4
     booking_id = resp.json['booking_id']
     booking = Booking.objects.get(id=booking_id)
@@ -452,8 +546,12 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
     resp = app.get('/api/booking/%s/ics/' % resp.json['booking_id'])
     assert resp.headers['Content-Type'] == 'text/calendar'
 
-    params = {'description': 'custom booking description', 'location': 'custom booking location',
-              'comment': 'custom comment', 'url': 'http://example.com/custom'}
+    params = {
+        'description': 'custom booking description',
+        'location': 'custom booking location',
+        'comment': 'custom comment',
+        'url': 'http://example.com/custom',
+    }
     resp = app.get('/api/booking/%s/ics/' % booking_id, params=params)
     assert 'DESCRIPTION:custom booking description\r\n' in resp.text
     assert 'LOCATION:custom booking location\r\n' in resp.text
@@ -470,10 +568,13 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
     booking = Booking.objects.get(id=resp.json['booking_id'])
     booking_ics = booking.get_ics()
     start = booking.event.start_datetime.strftime('%Y%m%dT%H%M%S')
-    end = (booking.event.start_datetime + datetime.timedelta(minutes=booking.event.meeting_type.duration)).strftime('%Y%m%dT%H%M%S')
+    end = (
+        booking.event.start_datetime + datetime.timedelta(minutes=booking.event.meeting_type.duration)
+    ).strftime('%Y%m%dT%H%M%S')
     assert "DTSTART:%sZ\r\n" % start in booking_ics
     assert "DTEND:%sZ\r\n" % end in booking_ics
 
+
 def test_booking_api_fillslots(app, some_data, user):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     events_ids = [x.id for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()]
@@ -520,9 +621,15 @@ def test_booking_api_fillslots(app, some_data, user):
     assert Booking.objects.filter(event__agenda=agenda, primary_booking=primary_booking_id_2).count() == 2
 
     # test with additional data
-    resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id,
-            params={'slots': events_ids,
-                    'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslots/' % agenda.id,
+        params={
+            'slots': events_ids,
+            'label': 'foo',
+            'user_name': 'bar',
+            'backoffice_url': 'http://example.net/',
+        },
+    )
     booking_id = resp.json['booking_id']
     assert Booking.objects.get(id=booking_id).label == 'foo'
     assert Booking.objects.get(id=booking_id).user_name == 'bar'
@@ -538,9 +645,10 @@ def test_booking_api_fillslots(app, some_data, user):
     assert Booking.objects.get(id=booking_id).cancellation_datetime is not None
 
     # extra data stored in extra_data field
-    resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id,
-            params={'slots': events_ids,
-                    'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'})
+    resp = app.post_json(
+        '/api/agenda/%s/fillslots/' % agenda.id,
+        params={'slots': events_ids, 'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'},
+    )
     assert Booking.objects.get(id=resp.json['booking_id']).label == 'l'
     assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'u'
     assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == ''
@@ -549,9 +657,11 @@ def test_booking_api_fillslots(app, some_data, user):
         assert booking.extra_data == {'foo': 'bar'}
 
     # test invalid data are refused
-    resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id,
-            params={'slots': events_ids,
-                    'user_name': {'foo': 'bar'}}, status=400)
+    resp = app.post_json(
+        '/api/agenda/%s/fillslots/' % agenda.id,
+        params={'slots': events_ids, 'user_name': {'foo': 'bar'}},
+        status=400,
+    )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'invalid payload'  # legacy
     assert resp.json['err_class'] == 'invalid payload'
@@ -583,13 +693,15 @@ def test_booking_api_fillslots(app, some_data, user):
     resp = app.post('/api/agenda/foobar/fillslots/', status=404)
     resp = app.post('/api/agenda/233/fillslots/', status=404)
 
+
 def test_booking_api_meeting(app, meetings_agenda, user):
     agenda_id = meetings_agenda.slug
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     event_id = resp.json['data'][2]['id']
-    assert urlparse.urlparse(resp.json['data'][2]['api']['fillslot_url']
-            ).path == '/api/agenda/%s/fillslot/%s/' % (meetings_agenda.slug, event_id)
+    assert urlparse.urlparse(
+        resp.json['data'][2]['api']['fillslot_url']
+    ).path == '/api/agenda/%s/fillslot/%s/' % (meetings_agenda.slug, event_id)
 
     app.authorization = ('Basic', ('john.doe', 'password'))
 
@@ -600,10 +712,12 @@ def test_booking_api_meeting(app, meetings_agenda, user):
     # make a booking
     resp_booking = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
     assert Booking.objects.count() == 1
-    assert resp_booking.json['datetime'] == localtime(Booking.objects.all()[0].event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
-    assert resp_booking.json['end_datetime'] == localtime(Booking.objects.all()[0].event.end_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(Booking.objects.all()[0].event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
+    assert resp_booking.json['end_datetime'] == localtime(
+        Booking.objects.all()[0].event.end_datetime
+    ).strftime('%Y-%m-%d %H:%M:%S')
     assert resp_booking.json['duration'] == 30
 
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
@@ -622,6 +736,7 @@ def test_booking_api_meeting(app, meetings_agenda, user):
     assert resp.json['err'] == 0
     assert Booking.objects.count() == 2
 
+
 def test_booking_api_meeting_fillslots(app, meetings_agenda, user):
     agenda_id = meetings_agenda.slug
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
@@ -633,10 +748,12 @@ def test_booking_api_meeting_fillslots(app, meetings_agenda, user):
     assert Booking.objects.count() == 2
     primary_booking = Booking.objects.filter(primary_booking__isnull=True).first()
     secondary_booking = Booking.objects.filter(primary_booking=primary_booking.id).first()
-    assert resp_booking.json['datetime'] == localtime(primary_booking.event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
-    assert resp_booking.json['end_datetime'] == localtime(secondary_booking.event.end_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(primary_booking.event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
+    assert resp_booking.json['end_datetime'] == localtime(secondary_booking.event.end_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
 
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len([x for x in resp2.json['data'] if not x.get('disabled')]) + 2
@@ -672,14 +789,13 @@ def test_booking_api_meeting_fillslots(app, meetings_agenda, user):
     assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 2
 
     impossible_slots = ['1:2017-05-22-1130', '2:2017-05-22-1100']
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda_id,
-                    params={'slots': impossible_slots},
-                    status=400)
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda_id, params={'slots': impossible_slots}, status=400)
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'all slots must have the same meeting type id (1)'  # legacy
     assert resp.json['err_class'] == 'all slots must have the same meeting type id (1)'
     assert resp.json['err_desc'] == 'all slots must have the same meeting type id (1)'
 
+
 def test_booking_api_meeting_across_daylight_saving_time(app, meetings_agenda, user):
     meetings_agenda.maximal_booking_delay = 365
     meetings_agenda.save()
@@ -689,19 +805,22 @@ def test_booking_api_meeting_across_daylight_saving_time(app, meetings_agenda, u
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     event_index = 26 * 18
     event_id = resp.json['data'][event_index]['id']
-    assert event_id[-4:] == resp.json['data'][2*18]['id'][-4:]
-    assert urlparse.urlparse(resp.json['data'][event_index]['api']['fillslot_url']
-            ).path == '/api/agenda/%s/fillslot/%s/' % (meetings_agenda.slug, event_id)
+    assert event_id[-4:] == resp.json['data'][2 * 18]['id'][-4:]
+    assert urlparse.urlparse(
+        resp.json['data'][event_index]['api']['fillslot_url']
+    ).path == '/api/agenda/%s/fillslot/%s/' % (meetings_agenda.slug, event_id)
 
     app.authorization = ('Basic', ('john.doe', 'password'))
     resp_booking = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
     assert Booking.objects.count() == 1
-    assert resp_booking.json['datetime'] == localtime(Booking.objects.all()[0].event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(Booking.objects.all()[0].event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert resp.json['data'][event_index]['disabled']
 
+
 def test_booking_api_meeting_different_durations_book_short(app, meetings_agenda, user):
     agenda_id = meetings_agenda.id
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
@@ -722,9 +841,12 @@ def test_booking_api_meeting_different_durations_book_short(app, meetings_agenda
 
     # the longer event at the same time shouldn't be available anymore
     resp_long2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
-    assert len(resp_long.json['data']) == len([x for x in resp_long2.json['data'] if not x.get('disabled')]) + 1
+    assert (
+        len(resp_long.json['data']) == len([x for x in resp_long2.json['data'] if not x.get('disabled')]) + 1
+    )
     assert resp_long.json['data'][1:] == [x for x in resp_long2.json['data'] if not x.get('disabled')]
 
+
 def test_booking_api_meeting_different_durations_book_long(app, meetings_agenda, user):
     agenda_id = meetings_agenda.id
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
@@ -745,7 +867,10 @@ def test_booking_api_meeting_different_durations_book_long(app, meetings_agenda,
 
     # this should have removed two short events
     resp_short2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type_2.id)
-    assert len(resp_short.json['data']) == len([x for x in resp_short2.json['data'] if not x.get('disabled')]) + 2
+    assert (
+        len(resp_short.json['data'])
+        == len([x for x in resp_short2.json['data'] if not x.get('disabled')]) + 2
+    )
 
     # book another long event
     event_id = resp.json['data'][10]['id']
@@ -754,15 +879,18 @@ def test_booking_api_meeting_different_durations_book_long(app, meetings_agenda,
     assert Booking.objects.count() == 2
 
     resp_short2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type_2.id)
-    assert len(resp_short.json['data']) == len([x for x in resp_short2.json['data'] if not x.get('disabled')]) + 4
+    assert (
+        len(resp_short.json['data'])
+        == len([x for x in resp_short2.json['data'] if not x.get('disabled')]) + 4
+    )
+
 
 def test_booking_api_with_data(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id)[0]
 
     app.authorization = ('Basic', ('john.doe', 'password'))
-    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id),
-            params={'hello': 'world'})
+    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), params={'hello': 'world'})
     assert Booking.objects.count() == 1
     assert Booking.objects.all()[0].extra_data == {'hello': 'world'}
 
@@ -801,11 +929,12 @@ def test_booking_api_available(app, some_data, meetings_agenda, user):
     assert 'places' not in resp.json
 
     # not for multiple booking
-    events = [x for x in Event.objects.filter(agenda=agenda).order_by('start_datetime') if x.in_bookable_period()][:2]
+    events = [
+        x for x in Event.objects.filter(agenda=agenda).order_by('start_datetime') if x.in_bookable_period()
+    ][:2]
     slots = [x.pk for x in events]
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': '3'})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': '3'})
     assert resp.json['err'] == 0
     assert 'places' not in resp.json
 
@@ -822,7 +951,7 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
     # Book a new event and cancel previous booking
     resp = app.post_json(
         '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
-        params={'cancel_booking_id': first_booking.pk}
+        params={'cancel_booking_id': first_booking.pk},
     )
     assert resp.json['err'] == 0
     assert resp.json['cancelled_booking_id'] == first_booking.pk
@@ -833,7 +962,7 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
     # Cancelling an already cancelled booking returns an error
     resp = app.post_json(
         '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
-        params={'cancel_booking_id': first_booking.pk}
+        params={'cancel_booking_id': first_booking.pk},
     )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'cancel booking: booking already cancelled'  # legacy
@@ -843,8 +972,7 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
 
     # Cancelling a non existent booking returns an error
     resp = app.post_json(
-        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
-        params={'cancel_booking_id': '-1'}
+        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id), params={'cancel_booking_id': '-1'}
     )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'cancel booking: booking does no exist'  # legacy
@@ -853,17 +981,14 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
     assert Booking.objects.count() == 2
 
     # Cancelling booking with different count than new booking
-    resp = app.post_json(
-        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_2.id),
-        params={'count': 2}
-    )
+    resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_2.id), params={'count': 2})
     assert resp.json['err'] == 0
     assert Booking.objects.count() == 4
     booking_id = resp.json['booking_id']
 
     resp = app.post_json(
         '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_3.id),
-        params={'cancel_booking_id': booking_id, 'count': 1}
+        params={'cancel_booking_id': booking_id, 'count': 1},
     )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'cancel booking: count is different'  # legacy
@@ -875,23 +1000,25 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
     app.post_json(
         '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id),
         params={'cancel_booking_id': 'no an integer'},
-        status=400)
+        status=400,
+    )
 
     # cancel_booking_id can be empty or null
     resp = app.post_json(
-        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id),
-        params={'cancel_booking_id': ''})
+        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id), params={'cancel_booking_id': ''}
+    )
     assert resp.json['err'] == 0
     assert 'cancelled_booking_id' not in resp.json
     assert Booking.objects.count() == 5
 
     resp = app.post_json(
-        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id),
-        params={'cancel_booking_id': None})
+        '/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id), params={'cancel_booking_id': None}
+    )
     assert resp.json['err'] == 0
     assert 'cancelled_booking_id' not in resp.json
     assert Booking.objects.count() == 6
 
+
 def test_booking_cancellation_api(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id)[0]
@@ -904,6 +1031,7 @@ def test_booking_cancellation_api(app, some_data, user):
     resp = app.delete('/api/booking/%s/' % booking_id)
     assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
 
+
 def test_booking_cancellation_post_api(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id)[0]
@@ -924,6 +1052,7 @@ def test_booking_cancellation_post_api(app, some_data, user):
     resp = app.post('/api/booking/%s/cancel/' % booking_id, status=200)
     assert resp.json['err'] == 1
 
+
 def test_booking_cancellation_post_meeting_api(app, meetings_agenda, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar Meeting')[0].id
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
@@ -948,6 +1077,7 @@ def test_booking_cancellation_post_meeting_api(app, meetings_agenda, user):
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len([x for x in resp.json['data'] if not x.get('disabled')]) == nb_events - 1
 
+
 def test_soldout(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
@@ -971,6 +1101,7 @@ def test_soldout(app, some_data, user):
     assert resp.json['err_class'] == 'sold out'
     assert resp.json['err_desc'] == 'sold out'
 
+
 def test_status(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id)[0]
@@ -1033,6 +1164,7 @@ def test_waiting_list_datetimes(app, some_data, user):
     assert not event.id in [x['id'] for x in resp.json['data'] if not x.get('disabled')]
     assert event.id in [x['id'] for x in resp.json['data'] if x.get('disabled')]
 
+
 def test_waiting_list_booking(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
@@ -1074,6 +1206,7 @@ def test_waiting_list_booking(app, some_data, user):
     assert resp.json['err_class'] == 'sold out'
     assert resp.json['err_desc'] == 'sold out'
 
+
 def test_accept_booking(app, some_data, user):
     agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
     event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
@@ -1107,12 +1240,15 @@ def test_accept_booking(app, some_data, user):
     assert Booking.objects.filter(in_waiting_list=True).count() == 1
     assert Booking.objects.filter(in_waiting_list=False).count() == 0
 
+
 def test_multiple_booking_api(app, some_data, user):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
 
     resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda.id)
-    event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api']['fillslot_url']
+    event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api'][
+        'fillslot_url'
+    ]
 
     app.authorization = ('Basic', ('john.doe', 'password'))
     resp = app.post('/api/agenda/%s/fillslot/%s/?count=NaN' % (agenda.slug, event.id), status=400)
@@ -1199,10 +1335,13 @@ def test_multiple_booking_api(app, some_data, user):
     assert Event.objects.get(id=event.id).booked_places == 3
     assert Event.objects.get(id=event.id).waiting_list == 2
 
+
 def test_multiple_booking_api_fillslots(app, some_data, user):
     agenda = Agenda.objects.filter(label=u'Foo bar')[0]
     # get slots of first 2 events
-    events = [x for x in Event.objects.filter(agenda=agenda).order_by('start_datetime') if x.in_bookable_period()][:2]
+    events = [
+        x for x in Event.objects.filter(agenda=agenda).order_by('start_datetime') if x.in_bookable_period()
+    ][:2]
     events_ids = [x.id for x in events]
     resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda.id)
     slots = [x['id'] for x in resp_datetimes.json['data'] if x['id'] in events_ids]
@@ -1214,8 +1353,9 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
     assert resp.json['err_class'] == "invalid value for count (NaN)"
     assert resp.json['err_desc'] == "invalid value for count (NaN)"
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 'NaN'}, status=400)
+    resp = app.post(
+        '/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 'NaN'}, status=400
+    )
     assert resp.json['err'] == 1
     assert resp.json['reason'] == "invalid payload"  # legacy
     assert resp.json['err_class'] == "invalid payload"
@@ -1223,8 +1363,7 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
     assert 'count' in resp.json['errors']
 
     # get 3 places on 2 slots
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': '3'})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': '3'})
     # one booking with 5 children
     booking = Booking.objects.get(id=resp.json['booking_id'])
     cancel_url = resp.json['api']['cancel_url']
@@ -1236,8 +1375,7 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
     for event in events:
         assert Event.objects.get(id=event.id).booked_places == 3
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 2})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 2})
     for event in events:
         assert Event.objects.get(id=event.id).booked_places == 5
 
@@ -1251,8 +1389,7 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
     events[0].waiting_list_places = 8
     events[0].save()
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 5})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 5})
     for event in events:
         assert Event.objects.get(id=event.id).booked_places == 2
         assert Event.objects.get(id=event.id).waiting_list == 5
@@ -1260,8 +1397,7 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
 
     return
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 5})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 5})
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'sold out'  # legacy
     assert resp.json['err_class'] == 'sold out'
@@ -1283,34 +1419,31 @@ def test_multiple_booking_api_fillslots(app, some_data, user):
     events[0].waiting_list_places = 2
     events[0].save()
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 5})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 5})
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'sold out'  # legacy
     assert resp.json['err_class'] == 'sold out'
     assert resp.json['err_desc'] == 'sold out'
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 3})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 3})
     assert resp.json['err'] == 0
     for event in events:
         assert Event.objects.get(id=event.id).booked_places == 3
         assert Event.objects.get(id=event.id).waiting_list == 0
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': 3})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': 3})
     assert resp.json['err'] == 1
     assert resp.json['reason'] == 'sold out'  # legacy
     assert resp.json['err_class'] == 'sold out'
     assert resp.json['err_desc'] == 'sold out'
 
-    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug,
-                    params={'slots': slots, 'count': '2'})
+    resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': slots, 'count': '2'})
     assert resp.json['err'] == 0
     for event in events:
         assert Event.objects.get(id=event.id).booked_places == 3
         assert Event.objects.get(id=event.id).waiting_list == 2
 
+
 def test_agenda_detail_api(app, some_data):
     agenda = Agenda.objects.get(slug='foo-bar')
     resp = app.get('/api/agenda/%s/' % agenda.slug)
@@ -1324,6 +1457,7 @@ def test_agenda_detail_api(app, some_data):
     # unknown
     app.get('/api/agenda/whatever/', status=404)
 
+
 def test_agenda_api_date_range(app, some_data):
     # test range limitation
     agenda2 = Agenda.objects.get(slug='foo-bar2')
@@ -1339,8 +1473,7 @@ def test_agenda_api_date_range(app, some_data):
             day_events = ['8:00']
         day = base_date + datetime.timedelta(days=idx)
         for event in day_events:
-            event_dt = datetime.datetime.combine(
-                day, datetime.datetime.strptime(event, '%H:%M').time())
+            event_dt = datetime.datetime.combine(day, datetime.datetime.strptime(event, '%H:%M').time())
             Event.objects.create(agenda=agenda2, start_datetime=make_aware(event_dt), places=2)
 
     params = {'date_start': base_date.isoformat()}
@@ -1380,6 +1513,7 @@ def test_agenda_api_date_range(app, some_data):
     assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
     assert resp.json['data'][-1]['datetime'] == '2017-05-30 11:00:00'
 
+
 def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
     app.authorization = ('Basic', ('john.doe', 'password'))
     agenda_id = meetings_agenda.slug
@@ -1396,15 +1530,19 @@ def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
     time_period = meetings_agenda.desk_set.first().timeperiod_set.first()
     desk2 = Desk.objects.create(label='Desk 2', agenda=meetings_agenda)
     TimePeriod.objects.create(
-        start_time=time_period.start_time, end_time=time_period.end_time,
-        weekday=time_period.weekday, desk=desk2)
+        start_time=time_period.start_time,
+        end_time=time_period.end_time,
+        weekday=time_period.weekday,
+        desk=desk2,
+    )
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     event_id = resp.json['data'][1]['id']
     resp_booking = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
     assert Booking.objects.count() == 2
-    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
 
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len([x for x in resp2.json['data'] if not x['disabled']]) + 1
@@ -1430,8 +1568,9 @@ def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
         resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
         queries_count_fillslot1 = len(ctx.captured_queries)
 
-    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
     cancel_url = resp.json['api']['cancel_url']
 
     resp3 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
@@ -1446,8 +1585,9 @@ def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
     resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
     assert Booking.objects.count() == 4
     assert Booking.objects.exclude(cancellation_datetime__isnull=True).count() == 2
-    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime
-            ).strftime('%Y-%m-%d %H:%M:%S')
+    assert resp_booking.json['datetime'] == localtime(Booking.objects.last().event.start_datetime).strftime(
+        '%Y-%m-%d %H:%M:%S'
+    )
 
     # try booking the same timeslot again and fail
     resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
@@ -1467,6 +1607,7 @@ def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
         app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
         assert queries_count_datetime1 == len(ctx.captured_queries)
 
+
 def test_agenda_meeting_api_fillslots_multiple_desks(app, meetings_agenda, user):
     app.authorization = ('Basic', ('john.doe', 'password'))
     agenda_id = meetings_agenda.slug
@@ -1476,8 +1617,11 @@ def test_agenda_meeting_api_fillslots_multiple_desks(app, meetings_agenda, user)
     time_period = meetings_agenda.desk_set.first().timeperiod_set.first()
     desk2 = Desk.objects.create(label='Desk 2', agenda=meetings_agenda)
     TimePeriod.objects.create(
-        start_time=time_period.start_time, end_time=time_period.end_time,
-        weekday=time_period.weekday, desk=desk2)
+        start_time=time_period.start_time,
+        end_time=time_period.end_time,
+        weekday=time_period.weekday,
+        desk=desk2,
+    )
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     slots = [x['id'] for x in resp.json['data'][:3]]
@@ -1485,6 +1629,7 @@ def test_agenda_meeting_api_fillslots_multiple_desks(app, meetings_agenda, user)
     def get_free_places():
         resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
         return len([x for x in resp.json['data'] if not x['disabled']])
+
     start_free_places = get_free_places()
 
     # booking 3 slots on desk 1
@@ -1541,6 +1686,7 @@ def test_agenda_meeting_api_fillslots_multiple_desks(app, meetings_agenda, user)
     assert resp.json['desk']['slug'] == desk1
     assert get_free_places() == start_free_places - len(slots)
 
+
 def test_agenda_meeting_same_day(app, meetings_agenda, mock_now, user):
     app.authorization = ('Basic', ('john.doe', 'password'))
     agenda = Agenda(label='Foo', kind='meetings')
@@ -1553,20 +1699,19 @@ def test_agenda_meeting_same_day(app, meetings_agenda, mock_now, user):
     desk2 = Desk.objects.create(label='bar', agenda=agenda)
     for weekday in range(7):
         TimePeriod.objects.create(
-            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30),
-            desk=desk1)
+            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30), desk=desk1
+        )
         TimePeriod.objects.create(
-            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30),
-            desk=desk2)
+            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30), desk=desk2
+        )
     resp = app.get(datetime_url)
     event_data = resp.json['data'][0]
     # check first proposed date is on the same day unless we're past the last
     # open timeperiod.
     event_datetime = datetime.datetime.strptime(event_data['datetime'], '%Y-%m-%d %H:%M:%S').timetuple()
-    assert (event_datetime[:3] == mock_now.timetuple()[:3] and
-            event_datetime[3:5] >= mock_now.timetuple()[3:5]) or (
-            event_datetime[:3] > mock_now.timetuple()[:3] and
-            event_datetime[3:5] < mock_now.timetuple()[3:5])
+    assert (
+        event_datetime[:3] == mock_now.timetuple()[:3] and event_datetime[3:5] >= mock_now.timetuple()[3:5]
+    ) or (event_datetime[:3] > mock_now.timetuple()[:3] and event_datetime[3:5] < mock_now.timetuple()[3:5])
 
     # check booking works
     first_booking_url = resp.json['data'][0]['api']['fillslot_url']
@@ -1598,8 +1743,8 @@ def test_agenda_meeting_next_day(app, meetings_agenda, mock_now, user):
     desk = Desk.objects.create(label='foo', agenda=agenda)
     for weekday in range(7):
         time_period = TimePeriod.objects.create(
-            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30),
-            desk=desk)
+            weekday=weekday, start_time=datetime.time(11, 0), end_time=datetime.time(12, 30), desk=desk
+        )
     resp = app.get(datetime_url)
     event_data = resp.json['data'][0]
     # check all proposed dates are on the next day
@@ -1631,8 +1776,10 @@ def test_agenda_meeting_api_exception(app, meetings_agenda, user):
     desk = meetings_agenda.desk_set.first()
     # test exception at the lowest limit
     excp1 = TimePeriodException.objects.create(
-        desk=desk, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)))
+        desk=desk,
+        start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
+    )
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len(resp2.json['data']) + 4
 
@@ -1650,7 +1797,8 @@ def test_agenda_meeting_api_exception(app, meetings_agenda, user):
     TimePeriodException.objects.create(
         desk=excp1.desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 15, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 23, 9, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 23, 9, 0)),
+    )
 
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len(resp2.json['data']) + 6
@@ -1659,8 +1807,11 @@ def test_agenda_meeting_api_exception(app, meetings_agenda, user):
     desk2 = Desk.objects.create(label='Desk 2', agenda=meetings_agenda)
     time_period = desk.timeperiod_set.first()
     TimePeriod.objects.create(
-        desk=desk2, start_time=time_period.start_time, end_time=time_period.end_time,
-        weekday=time_period.weekday)
+        desk=desk2,
+        start_time=time_period.start_time,
+        end_time=time_period.end_time,
+        weekday=time_period.weekday,
+    )
     resp3 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len(resp3.json['data']) + 2  # +2 because excp1 changed
 
@@ -1668,7 +1819,8 @@ def test_agenda_meeting_api_exception(app, meetings_agenda, user):
     TimePeriodException.objects.create(
         desk=desk2,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 9, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
+    )
     booking_url = resp3.json['data'][0]['api']['fillslot_url']
     resp = app.post(booking_url)
     assert resp.json['err'] == 1
@@ -1683,34 +1835,68 @@ def test_agenda_meeting_api_in_between_exceptions(app, meetings_agenda, user):
     TimePeriodException.objects.create(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
+    )
     resp2 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len(resp2.json['data']) + 4
     # exclude slots on 2017-05-30 and 2017-07-10
     date_2017_05_30 = datetime.datetime(2017, 5, 30).date()
     date_2017_07_10 = datetime.datetime(2017, 7, 10).date()
-    count_on_2017_05_30 = len([
-        datum for datum in resp.json['data'] if datetime_from_str(datum['datetime']).date() == date_2017_05_30])
-    count_on_2017_07_10 = len([
-        datum for datum in resp.json['data'] if datetime_from_str(datum['datetime']).date() == date_2017_07_10])
+    count_on_2017_05_30 = len(
+        [
+            datum
+            for datum in resp.json['data']
+            if datetime_from_str(datum['datetime']).date() == date_2017_05_30
+        ]
+    )
+    count_on_2017_07_10 = len(
+        [
+            datum
+            for datum in resp.json['data']
+            if datetime_from_str(datum['datetime']).date() == date_2017_07_10
+        ]
+    )
     TimePeriodException.objects.create(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 30, 8, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 30, 18, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 30, 18, 0)),
+    )
     TimePeriodException.objects.create(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 7, 10, 8, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 7, 10, 18, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 7, 10, 18, 0)),
+    )
     resp3 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp2.json['data']) == len(resp3.json['data']) + count_on_2017_05_30 + count_on_2017_07_10
-    assert len([datum for datum in resp3.json['data'] if datetime_from_str(datum['datetime']).date() == date_2017_05_30]) == 0
-    assert len([datum for datum in resp3.json['data'] if datetime_from_str(datum['datetime']).date() == date_2017_07_10]) == 0
+    assert (
+        len(
+            [
+                datum
+                for datum in resp3.json['data']
+                if datetime_from_str(datum['datetime']).date() == date_2017_05_30
+            ]
+        )
+        == 0
+    )
+    assert (
+        len(
+            [
+                datum
+                for datum in resp3.json['data']
+                if datetime_from_str(datum['datetime']).date() == date_2017_07_10
+            ]
+        )
+        == 0
+    )
     # with a second desk with the same time periods
     desk2 = Desk.objects.create(label='Desk 2', agenda=meetings_agenda)
     for time_period in desk.timeperiod_set.all():
         TimePeriod.objects.create(
-            desk=desk2, start_time=time_period.start_time, end_time=time_period.end_time,
-            weekday=time_period.weekday)
+            desk=desk2,
+            start_time=time_period.start_time,
+            end_time=time_period.end_time,
+            weekday=time_period.weekday,
+        )
     resp4 = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     assert len(resp.json['data']) == len(resp4.json['data'])
 
@@ -1722,8 +1908,11 @@ def test_agenda_meeting_api_desk_info(app, meetings_agenda, user):
     desk2 = Desk.objects.create(label='Desk 2', agenda=meetings_agenda)
     for time_period in desk.timeperiod_set.all():
         TimePeriod.objects.create(
-            desk=desk2, start_time=time_period.start_time, end_time=time_period.end_time,
-            weekday=time_period.weekday)
+            desk=desk2,
+            start_time=time_period.start_time,
+            end_time=time_period.end_time,
+            weekday=time_period.weekday,
+        )
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
     booking_url = resp.json['data'][0]['api']['fillslot_url']
     booking_url2 = resp.json['data'][3]['api']['fillslot_url']
@@ -1792,9 +1981,13 @@ def test_agenda_meeting_gcd_durations(app, meetings_agenda, user):
     assert Booking.objects.count() == 4
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type_20.id)
-    assert [x for x in resp.json['data'] if not x.get('disabled')][0]['datetime'].startswith('2017-05-22 12:00:00')
+    assert [x for x in resp.json['data'] if not x.get('disabled')][0]['datetime'].startswith(
+        '2017-05-22 12:00:00'
+    )
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type_30.id)
-    assert [x for x in resp.json['data'] if not x.get('disabled')][0]['datetime'].startswith('2017-05-22 12:00:00')
+    assert [x for x in resp.json['data'] if not x.get('disabled')][0]['datetime'].startswith(
+        '2017-05-22 12:00:00'
+    )
 
 
 def test_agenda_meeting_gcd_durations_and_exceptions(app, meetings_agenda, user):
@@ -1820,7 +2013,8 @@ def test_agenda_meeting_gcd_durations_and_exceptions(app, meetings_agenda, user)
     TimePeriodException.objects.create(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 20)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 0)),
+    )
 
     resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type_20.id)
     assert len(resp.json['data']) == 1
@@ -1830,13 +2024,18 @@ def test_agenda_meeting_gcd_durations_and_exceptions(app, meetings_agenda, user)
 
 def test_datetimes_api_meetings_agenda_start_hour_change(app, meetings_agenda):
     meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
-    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (
-            meeting_type.agenda.slug, meeting_type.slug)
+    api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (meeting_type.agenda.slug, meeting_type.slug)
 
     resp = app.get(api_url)
     dt = datetime.datetime.strptime(resp.json['data'][2]['id'].split(':')[1], '%Y-%m-%d-%H%M')
-    ev = Event(agenda=meetings_agenda, meeting_type=meeting_type,
-            places=1, full=False, start_datetime=make_aware(dt), desk=Desk.objects.first())
+    ev = Event(
+        agenda=meetings_agenda,
+        meeting_type=meeting_type,
+        places=1,
+        full=False,
+        start_datetime=make_aware(dt),
+        desk=Desk.objects.first(),
+    )
     ev.save()
     booking = Booking(event=ev)
     booking.save()
diff --git a/tests/test_api_utils.py b/tests/test_api_utils.py
index 365fa09..07ce4a9 100644
--- a/tests/test_api_utils.py
+++ b/tests/test_api_utils.py
@@ -3,13 +3,16 @@ import pytest
 from chrono.api.utils import Response
 
 
-@pytest.mark.parametrize('data, expected', [
-    (None, None),
-    ({}, {}),
-    ({'reason': 'foo'}, {'reason': 'foo'}),
-    ({'err_class': 'foo'}, {'err_class': 'foo', 'reason': 'foo'}),
-    ({'bar': 'foo'}, {'bar': 'foo'}),
-])
+@pytest.mark.parametrize(
+    'data, expected',
+    [
+        (None, None),
+        ({}, {}),
+        ({'reason': 'foo'}, {'reason': 'foo'}),
+        ({'err_class': 'foo'}, {'err_class': 'foo', 'reason': 'foo'}),
+        ({'bar': 'foo'}, {'bar': 'foo'}),
+    ],
+)
 def test_response_data(data, expected):
     resp = Response(data=data)
     assert resp.data == expected
diff --git a/tests/test_data_migrations.py b/tests/test_data_migrations.py
index 16244ea..cd3c8b0 100644
--- a/tests/test_data_migrations.py
+++ b/tests/test_data_migrations.py
@@ -1,7 +1,7 @@
 import datetime
-import pytest
 
 import django
+import pytest
 from django.db import connection
 from django.db.migrations.executor import MigrationExecutor
 from django.utils.timezone import make_aware
@@ -52,23 +52,31 @@ def test_timeperiod_data_migrations():
     Event = old_apps.get_model(app, 'Event')
     agenda = Agenda.objects.create(label='foo', slug='foo', kind='meetings')
     agenda2 = Agenda.objects.create(label='bar', slug='bar', kind='events')
-    TimePeriod.objects.create(agenda=agenda, weekday=1,
-                              start_time=datetime.time(8, 0),
-                              end_time=datetime.time(12, 0))
-    TimePeriod.objects.create(agenda=agenda, weekday=2,
-                              start_time=datetime.time(8, 0),
-                              end_time=datetime.time(10, 0))
-    TimePeriod.objects.create(agenda=agenda, weekday=3,
-                              start_time=datetime.time(9, 0),
-                              end_time=datetime.time(12, 0))
-    meeting_type = MeetingType.objects.create(agenda=agenda, label='foo',
-                                              slug='foo', duration=60)
-    Event.objects.create(agenda=agenda, places=1, meeting_type=meeting_type,
-                         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 9, 30)))
-    Event.objects.create(agenda=agenda, places=1, meeting_type=meeting_type,
-                         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)))
-    Event.objects.create(agenda=agenda2, places=5,
-                         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)))
+    TimePeriod.objects.create(
+        agenda=agenda, weekday=1, start_time=datetime.time(8, 0), end_time=datetime.time(12, 0)
+    )
+    TimePeriod.objects.create(
+        agenda=agenda, weekday=2, start_time=datetime.time(8, 0), end_time=datetime.time(10, 0)
+    )
+    TimePeriod.objects.create(
+        agenda=agenda, weekday=3, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
+    meeting_type = MeetingType.objects.create(agenda=agenda, label='foo', slug='foo', duration=60)
+    Event.objects.create(
+        agenda=agenda,
+        places=1,
+        meeting_type=meeting_type,
+        start_datetime=make_aware(datetime.datetime(2017, 5, 22, 9, 30)),
+    )
+    Event.objects.create(
+        agenda=agenda,
+        places=1,
+        meeting_type=meeting_type,
+        start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0)),
+    )
+    Event.objects.create(
+        agenda=agenda2, places=5, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 0))
+    )
     executor.loader.build_graph()
     executor.migrate(migrate_to)
     new_apps = executor.loader.project_state(migrate_to).apps
diff --git a/tests/test_import_export.py b/tests/test_import_export.py
index c3fa948..5cff139 100644
--- a/tests/test_import_export.py
+++ b/tests/test_import_export.py
@@ -3,24 +3,22 @@
 from __future__ import unicode_literals
 
 import datetime
-from io import StringIO
 import json
 import os
 import shutil
 import sys
 import tempfile
+from io import StringIO
 
 import pytest
 from django.contrib.auth.models import Group
-from django.core.management import call_command, CommandError
+from django.core.management import CommandError, call_command
 from django.utils.encoding import force_bytes
 from django.utils.timezone import make_aware
 
-from chrono.agendas.models import (Agenda, Event, TimePeriod, Desk,
-        TimePeriodException, AgendaImportError)
+from chrono.agendas.models import Agenda, AgendaImportError, Desk, Event, TimePeriod, TimePeriodException
 from chrono.manager.utils import import_site
-
-from test_api import some_data, meetings_agenda, time_zone, mock_now
+from test_api import meetings_agenda, mock_now, some_data, time_zone
 
 pytestmark = pytest.mark.django_db
 
@@ -40,10 +38,7 @@ def test_import_export(app, some_data, meetings_agenda):
     desk = meetings_agenda.desk_set.first()
     tpx_start = make_aware(datetime.datetime(2017, 5, 22, 8, 0))
     tpx_end = make_aware(datetime.datetime(2017, 5, 22, 12, 30))
-    TimePeriodException.objects.create(
-        desk=desk,
-        start_datetime=tpx_start,
-        end_datetime=tpx_end)
+    TimePeriodException.objects.create(desk=desk, start_datetime=tpx_start, end_datetime=tpx_end)
     output = get_output_of_command('export_site')
     assert len(json.loads(output)['agendas']) == 3
     import_site(data={}, clean=True)
@@ -77,15 +72,14 @@ def test_import_export(app, some_data, meetings_agenda):
     event.save()
     desk, _ = Desk.objects.get_or_create(agenda=agenda2, label='Desk A', slug='desk-a')
     timeperiod = TimePeriod(
-        desk=desk,
-        weekday=2,
-        start_time=datetime.time(10, 0),
-        end_time=datetime.time(11, 0))
+        desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
+    )
     timeperiod.save()
     exception = TimePeriodException(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
+    )
     exception.save()
 
     import_site(json.loads(output), overwrite=True)
@@ -97,15 +91,14 @@ def test_import_export(app, some_data, meetings_agenda):
     event = Event(agenda=agenda1, start_datetime=make_aware(datetime.datetime.now()), places=10)
     event.save()
     timeperiod = TimePeriod(
-        weekday=2,
-        desk=desk,
-        start_time=datetime.time(10, 0),
-        end_time=datetime.time(11, 0))
+        weekday=2, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
+    )
     timeperiod.save()
     exception = TimePeriodException(
         desk=desk,
         start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
-        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)))
+        end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
+    )
     exception.save()
     import_site(json.loads(output), overwrite=False)
     assert Event.objects.filter(id=event.id).count() == 1
diff --git a/tests/test_manager.py b/tests/test_manager.py
index dc4db09..8620c34 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -1,27 +1,27 @@
 # -*- coding: utf-8 -*-
 
 from __future__ import unicode_literals
+
 import copy
+import datetime
 import json
 
-from django.contrib.auth.models import User, Group
-from django.utils.encoding import force_text
-from django.utils.timezone import make_aware, now, localtime
-import datetime
 import freezegun
 import mock
 import pytest
 import requests
+from django.contrib.auth.models import Group, User
+from django.utils.encoding import force_text
+from django.utils.timezone import localtime, make_aware, now
 from webtest import Upload
 
-from chrono.wsgi import application
-
-from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
-                                   TimePeriod, Desk, TimePeriodException)
+from chrono.agendas.models import Agenda, Booking, Desk, Event, MeetingType, TimePeriod, TimePeriodException
 from chrono.manager.utils import export_site
+from chrono.wsgi import application
 
 pytestmark = pytest.mark.django_db
 
+
 @pytest.fixture
 def simple_user():
     try:
@@ -30,6 +30,7 @@ def simple_user():
         user = User.objects.create_user('user', password='user')
     return user
 
+
 @pytest.fixture
 def manager_user():
     try:
@@ -42,6 +43,7 @@ def manager_user():
     user.groups.set([group])
     return user
 
+
 @pytest.fixture
 def admin_user():
     try:
@@ -50,17 +52,20 @@ def admin_user():
         user = User.objects.create_superuser('admin', email=None, password='admin')
     return user
 
+
 @pytest.fixture
 def api_user():
     try:
         user = User.objects.get(username='api-user')
     except User.DoesNotExist:
-        user = User.objects.create(username='john.doe',
-                first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
+        user = User.objects.create(
+            username='john.doe', first_name=u'John', last_name=u'Doe', email='john.doe@example.net'
+        )
         user.set_password('password')
         user.save()
     return user
 
+
 def login(app, username='admin', password='admin'):
     login_page = app.get('/login/')
     login_form = login_page.forms[0]
@@ -70,15 +75,18 @@ def login(app, username='admin', password='admin'):
     assert resp.status_int == 302
     return app
 
+
 def test_unlogged_access(app):
     # connect while not being logged in
     assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
 
+
 def test_simple_user_access(app, simple_user):
     # connect while being logged as a simple user, access should be forbidden
     app = login(app, username='user', password='user')
     assert app.get('/manage/', status=403)
 
+
 def test_manager_user_access(app, manager_user):
     # connect while being logged as a manager user, access should be granted if
     # there's at least an agenda that is viewable or editable.
@@ -99,20 +107,24 @@ def test_manager_user_access(app, manager_user):
     agenda.save()
     assert app.get('/manage/', status=200)
 
+
 def test_home_redirect(app):
     assert app.get('/', status=302).location.endswith('/manage/')
 
+
 def test_access(app, admin_user):
     app = login(app)
     resp = app.get('/manage/', status=200)
     assert '<h2>Agendas</h2>' in resp.text
     assert "This site doesn't have any agenda yet." in resp.text
 
+
 def test_logout(app, admin_user):
     app = login(app)
     app.get('/logout/')
     assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
 
+
 def test_menu_json(app, admin_user):
     app = login(app)
     resp = app.get('/manage/menu.json', status=200)
@@ -123,6 +135,7 @@ def test_menu_json(app, admin_user):
     assert resp2.text == 'Q(%s);' % resp.text
     assert resp2.content_type == 'application/javascript'
 
+
 def test_view_agendas_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo Bar')
     agenda.view_role = manager_user.groups.all()[0]
@@ -156,6 +169,7 @@ def test_view_agendas_as_manager(app, manager_user):
     # check it gives a 404 on unknown agendas
     resp = app.get('/manage/agendas/%s/settings' % '9999', status=404)
 
+
 def test_add_agenda(app, admin_user):
     app = login(app)
     resp = app.get('/manage/', status=200)
@@ -169,6 +183,7 @@ def test_add_agenda(app, admin_user):
     assert 'Foo bar' in resp.text
     assert '<h2>Settings' in resp.text
 
+
 def test_add_agenda_as_manager(app, manager_user):
     # open /manage/ access to manager_user, and check agenda creation is not
     # allowed.
@@ -179,6 +194,7 @@ def test_add_agenda_as_manager(app, manager_user):
     resp = app.get('/manage/', status=200)
     resp = app.get('/manage/agendas/add/', status=403)
 
+
 def test_options_agenda(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
@@ -194,6 +210,7 @@ def test_options_agenda(app, admin_user):
     assert 'Foo baz' in resp.text
     assert '<h2>Settings' in resp.text
 
+
 def test_options_agenda_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.view_role = manager_user.groups.all()[0]
@@ -227,6 +244,7 @@ def test_options_agenda_as_manager(app, manager_user):
     assert 'Foo baz' in resp.text
     assert '<h2>Settings' in resp.text
 
+
 def test_delete_agenda(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
@@ -239,11 +257,11 @@ def test_delete_agenda(app, admin_user):
     resp = resp.follow()
     assert not 'Foo bar' in resp.text
 
+
 def test_delete_busy_agenda(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(start_datetime=now() + datetime.timedelta(days=10),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda)
     event.save()
 
     app = login(app)
@@ -272,6 +290,7 @@ def test_delete_busy_agenda(app, admin_user):
     booking.save()
     resp = resp.form.submit(status=403)
 
+
 def test_delete_agenda_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.edit_role = manager_user.groups.all()[0]
@@ -290,8 +309,7 @@ def test_delete_busy_desk(app, admin_user):
     desk_a = Desk.objects.create(agenda=agenda, label='Desk A')
     desk_b = Desk.objects.create(agenda=agenda, label='Desk B')
 
-    event = Event(start_datetime=now() + datetime.timedelta(days=10),
-                  places=10, agenda=agenda, desk=desk_a)
+    event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda, desk=desk_a)
     event.save()
 
     app = login(app)
@@ -354,6 +372,7 @@ def test_add_event_on_missing_agenda(app, admin_user):
     app = login(app)
     app.get('/manage/agendas/%s/add-event' % '999', status=404)
 
+
 def test_add_event_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.view_role = manager_user.groups.all()[0]
@@ -378,12 +397,11 @@ def test_add_event_as_manager(app, manager_user):
     assert 'Feb. 15, 2016, 5 p.m.' in resp.text
     assert '10 places' in resp.text
 
+
 def test_edit_event(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(
-            start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-            places=20, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=20, agenda=agenda)
     event.save()
     app = login(app)
     resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
@@ -397,16 +415,17 @@ def test_edit_event(app, admin_user):
     assert 'Feb. 16, 2016, 5 p.m.' in resp.text
     assert '20 places' in resp.text
 
+
 def test_edit_missing_event(app, admin_user):
     app = login(app)
     app.get('/manage/agendas/999/', status=404)
 
+
 def test_edit_event_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.view_role = manager_user.groups.all()[0]
     agenda.save()
-    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-                  places=20, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=20, agenda=agenda)
     event.save()
     app = login(app, username='manager', password='manager')
     resp = app.get('/manage/events/%s/' % event.id, status=403)
@@ -424,11 +443,11 @@ def test_edit_event_as_manager(app, manager_user):
     assert 'Feb. 16, 2016, 5 p.m.' in resp.text
     assert '20 places' in resp.text
 
+
 def test_booked_places(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
     event.save()
     Booking(event=event).save()
     Booking(event=event).save()
@@ -437,11 +456,11 @@ def test_booked_places(app, admin_user):
     assert '10 places' in resp.text
     assert '2 booked places' in resp.text
 
+
 def test_event_classes(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
     event.save()
     for i in range(2):
         Booking(event=event).save()
@@ -463,11 +482,11 @@ def test_event_classes(app, admin_user):
     assert 'full' in resp.text
     assert 'overbooking' in resp.text
 
+
 def test_delete_event(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
     event.save()
 
     app = login(app)
@@ -478,11 +497,11 @@ def test_delete_event(app, admin_user):
     assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
     assert Event.objects.count() == 0
 
+
 def test_delete_busy_event(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
-    event = Event(start_datetime=now() + datetime.timedelta(days=10),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda)
     event.save()
 
     app = login(app)
@@ -511,12 +530,12 @@ def test_delete_busy_event(app, admin_user):
     booking.save()
     resp = resp.form.submit(status=403)
 
+
 def test_delete_event_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.edit_role = manager_user.groups.all()[0]
     agenda.save()
-    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
-                  places=10, agenda=agenda)
+    event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
     event.save()
 
     app = login(app, username='manager', password='manager')
@@ -527,6 +546,7 @@ def test_delete_event_as_manager(app, manager_user):
     assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
     assert Event.objects.count() == 0
 
+
 def test_import_events(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
@@ -590,8 +610,9 @@ def test_import_events(app, admin_user):
     Event.objects.all().delete()
 
     resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
-    resp.form['events_csv_file'] = Upload('t.csv',
-            u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv')
+    resp.form['events_csv_file'] = Upload(
+        't.csv', u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv'
+    )
     resp = resp.form.submit(status=302)
     assert Event.objects.count() == 1
     assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
@@ -601,8 +622,9 @@ def test_import_events(app, admin_user):
     Event.objects.all().delete()
 
     resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
-    resp.form['events_csv_file'] = Upload('t.csv',
-            u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv')
+    resp.form['events_csv_file'] = Upload(
+        't.csv', u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv'
+    )
     resp = resp.form.submit(status=302)
     assert Event.objects.count() == 1
     assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
@@ -612,8 +634,9 @@ def test_import_events(app, admin_user):
     Event.objects.all().delete()
 
     resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
-    resp.form['events_csv_file'] = Upload('t.csv',
-            u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv')
+    resp.form['events_csv_file'] = Upload(
+        't.csv', u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv'
+    )
     resp = resp.form.submit(status=302)
     assert Event.objects.count() == 1
     assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
@@ -623,18 +646,23 @@ def test_import_events(app, admin_user):
     Event.objects.all().delete()
 
     resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
-    resp.form['events_csv_file'] = Upload('t.csv', b'date,time,etc.\n'
-                                                   b'2016-09-16,18:00,10,5,bla bla bla\n'
-                                                   b'\n'
-                                                   b'2016-09-19,18:00,10', 'text/csv')
+    resp.form['events_csv_file'] = Upload(
+        't.csv',
+        b'date,time,etc.\n' b'2016-09-16,18:00,10,5,bla bla bla\n' b'\n' b'2016-09-19,18:00,10',
+        'text/csv',
+    )
     resp = resp.form.submit(status=302)
     assert Event.objects.count() == 2
     Event.objects.all().delete()
 
     resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
-    resp.form['events_csv_file'] = Upload('t.csv', '"date"\t"time"\t"etc."\n'
-                                                   '"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
-                                                   '"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
+    resp.form['events_csv_file'] = Upload(
+        't.csv',
+        '"date"\t"time"\t"etc."\n'
+        '"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
+        '"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'),
+        'text/csv',
+    )
     resp = resp.form.submit(status=302)
     assert Event.objects.count() == 2
     Event.objects.all().delete()
@@ -671,6 +699,7 @@ def test_add_meetings_agenda(app, admin_user):
     agenda = Agenda.objects.get(label='Foo bar')
     assert agenda.kind == 'meetings'
 
+
 def test_meetings_agenda_add_meeting_type(app, admin_user):
     agenda = Agenda(label=u'Foo bar', kind='meetings')
     agenda.save()
@@ -693,6 +722,7 @@ def test_meetings_agenda_add_meeting_type(app, admin_user):
     resp = resp.form.submit()
     assert MeetingType.objects.get(agenda=agenda).duration == 30
 
+
 def test_meetings_agenda_delete_meeting_type(app, admin_user):
     agenda = Agenda(label=u'Foo bar', kind='meetings')
     agenda.save()
@@ -709,6 +739,7 @@ def test_meetings_agenda_delete_meeting_type(app, admin_user):
     assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
     assert MeetingType.objects.count() == 0
 
+
 def test_meetings_agenda_add_time_period(app, admin_user):
     agenda = Agenda(label=u'Foo bar', kind='meetings')
     agenda.save()
@@ -771,6 +802,7 @@ def test_meetings_agenda_add_time_period(app, admin_user):
     resp = resp.form.submit()
     assert TimePeriod.objects.filter(desk=desk).count() == 4
 
+
 def test_meetings_agenda_delete_time_period(app, admin_user):
     agenda = Agenda(label=u'Foo bar', kind='meetings')
     agenda.save()
@@ -778,9 +810,9 @@ def test_meetings_agenda_delete_time_period(app, admin_user):
     MeetingType(agenda=agenda, label='Blah').save()
 
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
-    time_period = TimePeriod(desk=desk, weekday=2,
-            start_time=datetime.time(10, 0),
-            end_time=datetime.time(18, 0))
+    time_period = TimePeriod(
+        desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
+    )
     time_period.save()
 
     app = login(app)
@@ -811,8 +843,9 @@ def test_meetings_agenda_add_time_period_as_manager(app, manager_user):
     resp = app.get('/manage/agendas/%d/settings' % agenda.id, status=403)
     MeetingType(agenda=agenda, label='Blah').save()
     app.get('/manage/agendas/%d/desk/%d/add-time-period' % (agenda.id, desk.id), status=403)
-    time_period = TimePeriod(desk=desk, weekday=0, start_time=datetime.time(9, 0),
-                             end_time=datetime.time(12, 0))
+    time_period = TimePeriod(
+        desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     time_period.save()
     resp = app.get('/manage/agendas/%d/' % agenda.id)
     app.get('/manage/timeperiods/%d/edit' % time_period.id, status=403)
@@ -915,8 +948,12 @@ def test_meetings_agenda_add_time_period_exception(app, admin_user):
     resp = resp.form.submit().follow()
     assert TimePeriodException.objects.count() == 1
     time_period_exception = TimePeriodException.objects.first()
-    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(hour=8).strftime(dt_format)
-    assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(hour=16).strftime(dt_format)
+    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(
+        hour=8
+    ).strftime(dt_format)
+    assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(
+        hour=16
+    ).strftime(dt_format)
     # add an exception beyond 2 weeks and make sure it isn't listed
     resp = resp.click('Add a time period exception', index=1)
     future = tomorrow + datetime.timedelta(days=15)
@@ -927,7 +964,9 @@ def test_meetings_agenda_add_time_period_exception(app, admin_user):
     assert TimePeriodException.objects.count() == 2
     assert 'Exception 1' in resp.text
     assert 'Exception 2' not in resp.text
-    resp = resp.click(href="/manage/time-period-exceptions/%d/exception-extract-list" % agenda.desk_set.first().pk)
+    resp = resp.click(
+        href="/manage/time-period-exceptions/%d/exception-extract-list" % agenda.desk_set.first().pk
+    )
     assert 'Exception 1' in resp.text
     assert 'Exception 2' in resp.text
 
@@ -936,16 +975,18 @@ def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admi
     agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
     MeetingType(agenda=agenda, label='Blah').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
-    event = Event.objects.create(agenda=agenda, places=1, desk=desk,
-                                 start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
+    event = Event.objects.create(
+        agenda=agenda, places=1, desk=desk, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
+    )
     Booking.objects.create(event=event)
     login(app)
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
     resp = resp.click('Add a time period exception')
-    resp = resp.form.submit() # submit empty form
+    resp = resp.form.submit()  # submit empty form
     # fields should be marked with errors
     assert resp.text.count('This field is required.') == 2
     # try again with data in fields
@@ -957,8 +998,9 @@ def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admi
 
     # check it's possible to add an exception on another desk
     desk = Desk.objects.create(agenda=agenda, label='Desk B')
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
     resp = resp.click('Add a time period exception', href='desk/%s/' % desk.id)
@@ -967,16 +1009,20 @@ def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admi
     resp = resp.form.submit()
     assert TimePeriodException.objects.count() == 1
 
+
 def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists(app, admin_user):
     agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
     MeetingType(agenda=agenda, label='Blah').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
-    event = Event.objects.create(agenda=agenda, places=1,
-                                 start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)))
-    Booking.objects.create(event=event,
-            cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30)))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
+    event = Event.objects.create(
+        agenda=agenda, places=1, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))
+    )
+    Booking.objects.create(
+        event=event, cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30))
+    )
     login(app)
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -987,12 +1033,14 @@ def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists
     assert 'One or several bookings exists within this time slot.' not in resp.text
     assert TimePeriodException.objects.count() == 1
 
+
 def test_meetings_agenda_add_invalid_time_period_exception(app, admin_user):
     agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
     MeetingType(agenda=agenda, label='Blah').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
     login(app)
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1007,8 +1055,9 @@ def test_meetings_agenda_delete_time_period_exception(app, admin_user):
     agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
     MeetingType(agenda=agenda, label='Blah').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
     login(app)
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1022,8 +1071,12 @@ def test_meetings_agenda_delete_time_period_exception(app, admin_user):
     resp = resp.form.submit().follow()
     assert TimePeriodException.objects.count() == 1
     time_period_exception = TimePeriodException.objects.first()
-    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(hour=8).strftime(dt_format)
-    assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(hour=16).strftime(dt_format)
+    assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(
+        hour=8
+    ).strftime(dt_format)
+    assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(
+        hour=16
+    ).strftime(dt_format)
     resp = resp.click(href='/manage/time-period-exceptions/%d/edit' % time_period_exception.id)
     resp = resp.click('Delete')
     resp = resp.form.submit().follow()
@@ -1035,7 +1088,8 @@ def test_meetings_agenda_delete_time_period_exception(app, admin_user):
         label='Future Exception',
         desk=desk,
         start_datetime=now() + datetime.timedelta(days=1),
-        end_datetime=now() + datetime.timedelta(days=2))
+        end_datetime=now() + datetime.timedelta(days=2),
+    )
     resp = app.get('/manage/time-period-exceptions/%d/exception-list' % desk.pk)
     resp = resp.click(href='/manage/time-period-exceptions/%d/delete' % time_period_exception.pk)
     resp = resp.form.submit(
@@ -1048,23 +1102,27 @@ def test_exception_list(app, admin_user):
     agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
     MeetingType(agenda=agenda, label='Blah').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
     past_exception = TimePeriodException.objects.create(
         label='Past Exception',
         desk=desk,
         start_datetime=now() - datetime.timedelta(days=2),
-        end_datetime=now() - datetime.timedelta(days=1))
+        end_datetime=now() - datetime.timedelta(days=1),
+    )
     current_exception = TimePeriodException.objects.create(
         label='Current Exception',
         desk=desk,
         start_datetime=now() - datetime.timedelta(days=1),
-        end_datetime=now() + datetime.timedelta(days=1))
+        end_datetime=now() + datetime.timedelta(days=1),
+    )
     future_exception = TimePeriodException.objects.create(
         label='Future Exception',
         desk=desk,
         start_datetime=now() + datetime.timedelta(days=1),
-        end_datetime=now() + datetime.timedelta(days=2))
+        end_datetime=now() + datetime.timedelta(days=2),
+    )
 
     login(app)
     resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
@@ -1092,8 +1150,9 @@ def test_agenda_import_time_period_exception_from_ics(app, admin_user):
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1150,9 +1209,9 @@ def test_agenda_import_time_period_exception_from_ics_recurrent(app, admin_user)
     agenda = Agenda.objects.create(label='Example', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Test Desk')
     MeetingType(agenda=agenda, label='Foo').save()
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                              start_time=datetime.time(10, 0),
-                              end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
     login(app)
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1182,8 +1241,9 @@ def test_agenda_import_time_period_exception_with_remote_ics(mocked_get, app, ad
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1193,7 +1253,7 @@ def test_agenda_import_time_period_exception_with_remote_ics(mocked_get, app, ad
     assert 'ics_url' in resp.form.fields
     resp.form['ics_url'] = 'http://example.com/foo.ics'
     mocked_response = mock.Mock()
-    mocked_response.text =  """BEGIN:VCALENDAR
+    mocked_response.text = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//foo.bar//EN
 BEGIN:VEVENT
@@ -1213,8 +1273,10 @@ END:VCALENDAR"""
     resp = resp.click('upload')
     resp.form['ics_url'] = ''
     resp = resp.form.submit(status=302)
-    assert not TimePeriodException.objects.filter(desk=desk,
-                    external_id='desk-%s:random-event-id' % desk.id).exists()
+    assert not TimePeriodException.objects.filter(
+        desk=desk, external_id='desk-%s:random-event-id' % desk.id
+    ).exists()
+
 
 @mock.patch('chrono.agendas.models.requests.get')
 def test_agenda_import_time_period_exception_with_remote_ics_no_events(mocked_get, app, admin_user):
@@ -1226,15 +1288,16 @@ def test_agenda_import_time_period_exception_with_remote_ics_no_events(mocked_ge
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
     resp = resp.click('upload')
     resp.form['ics_url'] = 'http://example.com/foo.ics'
     mocked_response = mock.Mock()
-    mocked_response.text =  """BEGIN:VCALENDAR
+    mocked_response.text = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//foo.bar//EN
 BEGIN:VEVENT
@@ -1257,8 +1320,7 @@ END:VCALENDAR"""
     resp = resp.click('Settings')
     resp = resp.click('upload')
     resp = resp.form.submit(status=302)
-    assert not TimePeriodException.objects.filter(desk=desk,
-                    external_id='random-event-id').exists()
+    assert not TimePeriodException.objects.filter(desk=desk, external_id='random-event-id').exists()
 
 
 @mock.patch('chrono.agendas.models.requests.get')
@@ -1271,15 +1333,16 @@ def test_agenda_update_time_period_exception_from_remote_ics(mocked_get, app, ad
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
     resp = resp.click('upload')
     resp.form['ics_url'] = 'http://example.com/foo.ics'
     mocked_response = mock.Mock()
-    mocked_response.text =  """BEGIN:VCALENDAR
+    mocked_response.text = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//foo.bar//EN
 BEGIN:VEVENT
@@ -1316,8 +1379,11 @@ END:VCALENDAR"""
     resp = resp.form.submit(status=302)
     assert TimePeriodException.objects.filter(desk=desk).count() == 1
 
+
 @mock.patch('chrono.agendas.models.requests.get')
-def test_agenda_import_time_period_exception_from_remote_ics_with_connection_error(mocked_get, app, admin_user):
+def test_agenda_import_time_period_exception_from_remote_ics_with_connection_error(
+    mocked_get, app, admin_user
+):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='New Desk')
     MeetingType(agenda=agenda, label='Bar').save()
@@ -1326,8 +1392,9 @@ def test_agenda_import_time_period_exception_from_remote_ics_with_connection_err
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1338,12 +1405,15 @@ def test_agenda_import_time_period_exception_from_remote_ics_with_connection_err
     resp.form['ics_url'] = 'http://example.com/foo.ics'
     mocked_response = mock.Mock()
     mocked_get.return_value = mocked_response
+
     def mocked_requests_connection_error(*args, **kwargs):
         raise requests.exceptions.ConnectionError('unreachable')
+
     mocked_get.side_effect = mocked_requests_connection_error
     resp = resp.form.submit(status=200)
     assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, unreachable).' in resp.text
 
+
 @mock.patch('chrono.agendas.models.requests.get')
 def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_get, app, admin_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
@@ -1354,8 +1424,9 @@ def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_ge
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
 
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1364,12 +1435,15 @@ def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_ge
     mocked_response = mock.Mock()
     mocked_response.status_code = 403
     mocked_get.return_value = mocked_response
+
     def mocked_requests_http_forbidden_error(*args, **kwargs):
         raise requests.exceptions.HTTPError(response=mocked_response)
+
     mocked_get.side_effect = mocked_requests_http_forbidden_error
     resp = resp.form.submit(status=200)
     assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, HTTP error 403).' in resp.text
 
+
 @mock.patch('chrono.agendas.models.requests.get')
 def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mocked_get, app, admin_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
@@ -1379,8 +1453,9 @@ def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mock
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
     assert 'Import exceptions from .ics' not in resp.text
-    TimePeriod.objects.create(weekday=1, desk=desk,
-                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
+    TimePeriod.objects.create(
+        weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
+    )
 
     resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
     resp = resp.click('Settings')
@@ -1388,12 +1463,15 @@ def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mock
     resp.form['ics_url'] = 'https://example.com/foo.ics'
     mocked_response = mock.Mock()
     mocked_get.return_value = mocked_response
+
     def mocked_requests_http_ssl_error(*args, **kwargs):
         raise requests.exceptions.SSLError('SSL error')
+
     mocked_get.side_effect = mocked_requests_http_ssl_error
     resp = resp.form.submit(status=200)
     assert 'Failed to retrieve remote calendar (https://example.com/foo.ics, SSL error).' in resp.text
 
+
 def test_agenda_day_view(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='New Desk')
@@ -1409,9 +1487,9 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
     resp = resp.follow()
     assert 'No opening hours this day.' in resp.text  # no time pediod
 
-    timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
-            start_time=datetime.time(10, 0),
-            end_time=datetime.time(18, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
+    )
     timeperiod.save()
     resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
     assert not 'No opening hours this day.' in resp.text
@@ -1434,14 +1512,12 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
     booking_url = resp.json['data'][0]['api']['fillslot_url']
     booking_url2 = resp.json['data'][2]['api']['fillslot_url']
     resp = app.post(booking_url)
-    resp = app.post_json(booking_url2,
-            params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
+    resp = app.post_json(booking_url2, params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
 
     app.reset()
     login(app)
     date = Booking.objects.all()[0].event.start_datetime
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda.id, date.year, date.month, date.day))
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
     assert resp.text.count('div class="booking') == 2
     assert 'hourspan-2' in resp.text  # table CSS class
     assert 'height: 50%; top: 0%;' in resp.text  # booking cells
@@ -1450,8 +1526,7 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
     # (and visually this will give more room for events)
     meetingtype = MeetingType(agenda=agenda, label='Baz', duration=15)
     meetingtype.save()
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda.id, date.year, date.month, date.day))
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
     assert resp.text.count('div class="booking') == 2
     assert 'hourspan-4' in resp.text  # table CSS class
 
@@ -1464,29 +1539,26 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
 
     app.reset()
     login(app)
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda.id, date.year, date.month, date.day))
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
     assert resp.text.count('div class="booking') == 1
 
     # wrong type
     agenda2 = Agenda(label=u'Foo bar')
     agenda2.save()
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda2.id, date.year, date.month, date.day), status=404)
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda2.id, date.year, date.month, date.day), status=404)
 
     # not enough permissions
     agenda2.view_role = manager_user.groups.all()[0]
     agenda2.save()
     app.reset()
     app = login(app, username='manager', password='manager')
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda.id, date.year, date.month, date.day), status=403)
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=403)
 
     # just enough permissions
     agenda.view_role = manager_user.groups.all()[0]
     agenda.save()
-    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
-        agenda.id, date.year, date.month, date.day), status=200)
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200)
+
 
 def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
@@ -1498,9 +1570,9 @@ def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
 
     today = datetime.date.today()
 
-    timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
-            start_time=datetime.time(10, 0),
-            end_time=datetime.time(23, 30))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(23, 30)
+    )
     timeperiod.save()
 
     login(app)
@@ -1508,6 +1580,7 @@ def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
     assert resp.text.count('<tr') == 15
     assert '<th class="hour">11 p.m.</th>' in resp.text
 
+
 def test_agenda_invalid_day_view(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='New Desk')
@@ -1520,6 +1593,7 @@ def test_agenda_invalid_day_view(app, admin_user, manager_user, api_user):
     resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, 2018, 11, 31), status=302)
     assert resp.location.endswith('2018/11/30/')
 
+
 def test_agenda_month_view(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='Passeports', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
@@ -1535,20 +1609,20 @@ def test_agenda_month_view(app, admin_user, manager_user, api_user):
     today = datetime.date.today()
     assert resp.request.url.endswith('%s/%s/' % (today.year, today.month))
 
-    assert 'Day view' in resp.text # date view link should be present
+    assert 'Day view' in resp.text  # date view link should be present
     assert 'No opening hours this month.' in resp.text
 
     today = datetime.date(2018, 11, 10)  # fixed day
     timeperiod_weekday = today.weekday()
-    timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
-            start_time=datetime.time(10, 0),
-            end_time=datetime.time(18, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
+    )
     timeperiod.save()
     resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
     assert not 'No opening hours this month.' in resp.text
     assert not '<div class="booking' in resp.text
     first_month_day = today.replace(day=1)
-    last_month_day = today.replace(day=1, month=today.month+1) - datetime.timedelta(days=1)
+    last_month_day = today.replace(day=1, month=today.month + 1) - datetime.timedelta(days=1)
     start_week_number = first_month_day.isocalendar()[1]
     end_week_number = last_month_day.isocalendar()[1]
     weeks_number = end_week_number - start_week_number + 1
@@ -1564,19 +1638,17 @@ def test_agenda_month_view(app, admin_user, manager_user, api_user):
     booking_url = resp.json['data'][0]['api']['fillslot_url']
     booking_url2 = resp.json['data'][2]['api']['fillslot_url']
     booking = app.post(booking_url)
-    booking_2 = app.post_json(booking_url2,
-            params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
+    booking_2 = app.post_json(booking_url2, params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
 
     app.reset()
     login(app)
     date = Booking.objects.all()[0].event.start_datetime
-    resp = app.get('/manage/agendas/%s/%d/%d/' % (
-        agenda.id, date.year, date.month))
-    assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
+    resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, date.year, date.month))
+    assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2  # booking cells
     desk = Desk.objects.create(agenda=agenda, label='Desk B')
-    timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
-            start_time=datetime.time(10, 0),
-            end_time=datetime.time(18, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
+    )
     timeperiod.save()
 
     app.reset()
@@ -1613,6 +1685,7 @@ def test_agenda_month_view(app, admin_user, manager_user, api_user):
     resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
     assert not 'No opening hours this month.' in resp.text
 
+
 def test_agenda_month_view_dst_change(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='Passeports', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
@@ -1621,9 +1694,9 @@ def test_agenda_month_view_dst_change(app, admin_user, manager_user, api_user):
     meetingtype.save()
 
     for weekday in range(0, 7):  # open all mornings
-        TimePeriod(desk=desk, weekday=weekday,
-                start_time=datetime.time(9, 0),
-                end_time=datetime.time(12, 0)).save()
+        TimePeriod(
+            desk=desk, weekday=weekday, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+        ).save()
 
     login(app)
     for date in ('2019-10-01', '2019-10-31'):
@@ -1658,6 +1731,7 @@ def test_import_agenda_as_manager(app, manager_user):
     resp = app.get('/manage/', status=200)
     resp = app.get('/manage/agendas/import/', status=403)
 
+
 def test_import_agenda(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
diff --git a/tests/test_misc.py b/tests/test_misc.py
index c1761ba..c2610b1 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -1,5 +1,6 @@
 from chrono.manager.widgets import DateTimeWidget, TimeWidget
 
+
 def test_widgets_init():
     DateTimeWidget()
     TimeWidget()
diff --git a/tests/test_sso.py b/tests/test_sso.py
index a8254c6..8e521ab 100644
--- a/tests/test_sso.py
+++ b/tests/test_sso.py
@@ -1,11 +1,11 @@
 import pytest
-
 from django.test import override_settings
 
 from chrono.wsgi import application
 
 pytestmark = pytest.mark.django_db
 
+
 def test_sso(app):
     with override_settings(MELLON_IDENTITY_PROVIDERS=[{'METADATA': 'x', 'ENTITY_ID': 'x'}]):
         resp = app.get('/login/')
@@ -14,6 +14,7 @@ def test_sso(app):
         resp = app.get('/login/?next=/manage/')
         assert resp.location.endswith('/accounts/mellon/login/?next=/manage/')
 
+
 def test_slo(app):
     with override_settings(MELLON_IDENTITY_PROVIDERS=[{'METADATA': 'x', 'ENTITY_ID': 'x'}]):
         resp = app.get('/logout/')
diff --git a/tests/test_time_periods.py b/tests/test_time_periods.py
index 8e3d521..10e344c 100644
--- a/tests/test_time_periods.py
+++ b/tests/test_time_periods.py
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 
 import datetime
-import pytest
 
+import pytest
 from django.test import override_settings
 from django.utils.encoding import force_text
 from django.utils.timezone import localtime, make_aware
 
-from chrono.agendas.models import Agenda, TimePeriod, TimePeriodException, MeetingType, Desk
+from chrono.agendas.models import Agenda, Desk, MeetingType, TimePeriod, TimePeriodException
 
 pytestmark = pytest.mark.django_db
 
@@ -18,13 +18,14 @@ def test_timeperiod_time_slots():
     desk = Desk.objects.create(label='Desk 1', agenda=agenda)
     meeting_type = MeetingType(duration=60, agenda=agenda)
     meeting_type.save()
-    timeperiod = TimePeriod(desk=desk, weekday=0,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 5, 9, 0)
     assert events[1].start_datetime.timetuple()[:5] == (2016, 9, 5, 10, 0)
@@ -35,52 +36,56 @@ def test_timeperiod_time_slots():
     assert len(events) == 12
 
     # another start before the timeperiod
-    timeperiod = TimePeriod(desk=desk, weekday=1,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=1, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 6, 9, 0)
     assert events[-1].start_datetime.timetuple()[:5] == (2016, 9, 27, 11, 0)
     assert len(events) == 12
 
     # a start on the day of the timeperiod
-    timeperiod = TimePeriod(desk=desk, weekday=3,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=3, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 1, 9, 0)
     assert events[-1].start_datetime.timetuple()[:5] == (2016, 9, 29, 11, 0)
     assert len(events) == 15
 
     # a start after the day of the timeperiod
-    timeperiod = TimePeriod(desk=desk, weekday=4,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=4, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 2, 9, 0)
     assert events[-1].start_datetime.timetuple()[:5] == (2016, 9, 30, 11, 0)
     assert len(events) == 15
 
     # another start after the day of the timeperiod
-    timeperiod = TimePeriod(desk=desk, weekday=5,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=5, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 3, 9, 0)
     assert events[-1].start_datetime.timetuple()[:5] == (2016, 9, 24, 11, 0)
@@ -89,13 +94,14 @@ def test_timeperiod_time_slots():
     # shorter duration -> double the events
     meeting_type.duration = 30
     meeting_type.save()
-    timeperiod = TimePeriod(desk=desk, weekday=5,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=5, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 3, 9, 0)
     assert events[-1].start_datetime.timetuple()[:5] == (2016, 9, 24, 11, 30)
@@ -105,28 +111,48 @@ def test_timeperiod_time_slots():
 @override_settings(LANGUAGE_CODE='fr-fr')
 def test_time_period_exception_as_string():
     # single day
-    assert force_text(TimePeriodException(
-        start_datetime=make_aware(datetime.datetime(2018, 1, 18)),
-        end_datetime=make_aware(datetime.datetime(2018, 1, 19)))
-        ) == u'18 jan. 2018'
+    assert (
+        force_text(
+            TimePeriodException(
+                start_datetime=make_aware(datetime.datetime(2018, 1, 18)),
+                end_datetime=make_aware(datetime.datetime(2018, 1, 19)),
+            )
+        )
+        == u'18 jan. 2018'
+    )
 
     # multiple full days
-    assert force_text(TimePeriodException(
-        start_datetime=make_aware(datetime.datetime(2018, 1, 18)),
-        end_datetime=make_aware(datetime.datetime(2018, 1, 20)))
-        ) == u'18 jan. 2018 → 20 jan. 2018'
+    assert (
+        force_text(
+            TimePeriodException(
+                start_datetime=make_aware(datetime.datetime(2018, 1, 18)),
+                end_datetime=make_aware(datetime.datetime(2018, 1, 20)),
+            )
+        )
+        == u'18 jan. 2018 → 20 jan. 2018'
+    )
 
     # a few hours in a day
-    assert force_text(TimePeriodException(
-        start_datetime=make_aware(datetime.datetime(2018, 1, 18, 10, 0)),
-        end_datetime=make_aware(datetime.datetime(2018, 1, 18, 12, 0)))
-        ) == u'18 jan. 2018 10:00 → 12:00'
+    assert (
+        force_text(
+            TimePeriodException(
+                start_datetime=make_aware(datetime.datetime(2018, 1, 18, 10, 0)),
+                end_datetime=make_aware(datetime.datetime(2018, 1, 18, 12, 0)),
+            )
+        )
+        == u'18 jan. 2018 10:00 → 12:00'
+    )
 
     # multiple days and different times
-    assert force_text(TimePeriodException(
-        start_datetime=make_aware(datetime.datetime(2018, 1, 18, 10, 0)),
-        end_datetime=make_aware(datetime.datetime(2018, 1, 20, 12, 0)))
-        ) == u'18 jan. 2018 10:00 → 20 jan. 2018 12:00'
+    assert (
+        force_text(
+            TimePeriodException(
+                start_datetime=make_aware(datetime.datetime(2018, 1, 18, 10, 0)),
+                end_datetime=make_aware(datetime.datetime(2018, 1, 20, 12, 0)),
+            )
+        )
+        == u'18 jan. 2018 10:00 → 20 jan. 2018 12:00'
+    )
 
 
 def test_desk_opening_hours():
@@ -139,18 +165,14 @@ def test_desk_opening_hours():
     assert len(hours) == 0
 
     # morning
-    TimePeriod(desk=desk, weekday=0,
-            start_time=datetime.time(9, 0),
-            end_time=datetime.time(12, 0)).save()
+    TimePeriod(desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)).save()
     hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
     assert len(hours) == 1
     assert hours[0].begin.time() == datetime.time(9, 0)
     assert hours[0].end.time() == datetime.time(12, 0)
 
     # and afternoon
-    TimePeriod(desk=desk, weekday=0,
-            start_time=datetime.time(14, 0),
-            end_time=datetime.time(17, 0)).save()
+    TimePeriod(desk=desk, weekday=0, start_time=datetime.time(14, 0), end_time=datetime.time(17, 0)).save()
     hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
     assert len(hours) == 2
     assert hours[0].begin.time() == datetime.time(9, 0)
@@ -161,9 +183,10 @@ def test_desk_opening_hours():
 
     # full day exception
     exception = TimePeriodException(
-            desk=desk,
-            start_datetime=make_aware(datetime.datetime(2018, 1, 22)),
-            end_datetime=make_aware(datetime.datetime(2018, 1, 23)))
+        desk=desk,
+        start_datetime=make_aware(datetime.datetime(2018, 1, 22)),
+        end_datetime=make_aware(datetime.datetime(2018, 1, 23)),
+    )
     exception.save()
 
     hours = list(desk.get_opening_hours(datetime.date(2018, 1, 22)))
@@ -200,13 +223,14 @@ def test_timeperiod_midnight_overlap_time_slots():
     desk = Desk.objects.create(label='Desk 1', agenda=agenda)
     meeting_type = MeetingType(duration=120, agenda=agenda)
     meeting_type.save()
-    timeperiod = TimePeriod(desk=desk, weekday=0,
-            start_time=datetime.time(21, 0),
-            end_time=datetime.time(23, 0))
+    timeperiod = TimePeriod(
+        desk=desk, weekday=0, start_time=datetime.time(21, 0), end_time=datetime.time(23, 0)
+    )
     events = timeperiod.get_time_slots(
-            min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
-            max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
-            meeting_type=meeting_type)
+        min_datetime=make_aware(datetime.datetime(2016, 9, 1)),
+        max_datetime=make_aware(datetime.datetime(2016, 10, 1)),
+        meeting_type=meeting_type,
+    )
     events = list(sorted(events, key=lambda x: x.start_datetime))
     assert events[0].start_datetime.timetuple()[:5] == (2016, 9, 5, 21, 0)
     assert events[1].start_datetime.timetuple()[:5] == (2016, 9, 12, 21, 0)
-- 
2.20.1

